Sur la base d'une sélection, je peux retourner x lignes comme ceci:
1 2019-07-23 10:14:04.000
1 2019-07-23 10:14:11.000
2 2019-07-23 10:45:32.000
1 2019-07-23 10:45:33.000
Nous avons toutes les millisecondes avec 0.
Existe-t-il un moyen d'ajouter 1 par 1 millisecondes, de sorte que la sélection ressemble à ceci:
1 2019-07-23 10:14:04.001
1 2019-07-23 10:14:11.002
2 2019-07-23 10:45:32.003
1 2019-07-23 10:45:33.004
J'essaie de créer un curseur ou même une mise à jour sans succès.
Voici la requête pour obtenir les résultats que je souhaite:
select top 10 ModifiedOn
from [SCHEMA].[dbo].[TABLE]
where FIELD between '2019-07-23 00:00' and '2019-07-23 23:59'
Il y a 81k valeurs. Le champ est DATETIME
.
Datetime
n'est pas précis au niveau de 1 milliseconde. Ce que vous demandez n'est possible que si vous changez de type de données (par exemple datetime2
).
Devis important:
Précision Arrondie à des incréments de .000, .003 ou .007 secondes
La fonction DateAdd
est ce que vous recherchez.
Utilisez millisecond
comme premier paramètre de la fonction pour lui indiquer que vous ajoutez des millisecondes. Utilisez ensuite 1
comme deuxième paramètre, pour le nombre de millisecondes à ajouter.
Voici un exemple, en saisissant l'heure actuelle dans une variable, puis en y ajoutant une milliseconde et en enregistrant le résultat en tant que deuxième variable, puis en imprimant chaque variable
Declare @RightNow as DateTime2
Declare @RightNowPlusAMillisecond as DateTime2
Select @RightNow = Getdate()
Select @RightNowPlusAMillisecond = DateAdd(millisecond,1,@RightNow)
Print @RightNow
Print @RightNowPlusAMillisecond
Résultats:
2019-07-23 08:25:38.3500000
2019-07-23 08:25:38.3510000
Remarque:
Comme Forrest le souligne dans une autre réponse, le type de données datetime
ne garantit pas la précision en millisecondes. Il arrondit à des incréments de .000, .003 ou .007 secondes. Si vous voulez une précision en millisecondes, utilisez datetime2
.
@ Doug-Deden a le bon point de départ, mais je voulais juste essayer de répondre à ce que je pensais être l'intention initiale de la question - comment l'appliquer à un jeu de résultats avec des millisecondes croissantes par ligne.
Dans ce cas, vous pouvez utiliser ROW_NUMBER et a Common Table Expression (modifier selon les besoins pour la structure de votre table, y compris les jointures, etc.).
Sélectionnez pour afficher les valeurs:
;WITH CTE AS (
SELECT t.my_id, t.my_date_column, ROW_NUMBER() OVER (ORDER BY my_date_column, my_id DESC) AS R
FROM Table1 t
)
SELECT TOP 1000 *, DATEADD(MILLISECOND, R, CAST(my_date_column AS datetime2)) [new_date]
FROM CTE
ORDER BY my_date_column
Mettre à jour les jointures à la table d'origine:
;WITH CTE AS (
SELECT t.my_id, t.my_date_column, ROW_NUMBER() OVER (ORDER BY my_date_column, my_id DESC) AS R
FROM Table1 t
)
UPDATE t SET
my_date_column = DATEADD(MILLISECOND, R, CAST(my_date_column AS datetime2))
FROM CTE c
JOIN Table1 t ON c.my_id = t.my_id
Je l'ai fait en utilisant DATETIME2(3)
.
Comme vous pouvez le voir sur la requête ci-dessous, c'est plus economic
:
declare @dt1 datetime2(3)
declare @dt2 datetime2
SELECT @DT1 = SYSDATETIME()
SELECT @DT2= SYSDATETIME()
SELECT [THE LENGTH OF DATETIME2]=DATALENGTH(@DT2)
,[THE LENGTH OF DATETIME2(3)]=DATALENGTH(@DT1)
Les différences entre datetime
et datetime2
sont bien expliqués ici .
Pour cet exercice, je crée une table temporaire à des fins de test et je la remplis avec 999 random dates
de 01-jan-2019
et aujourd'hui (23-july-2019
)
puis dans l'ordre, j'ai mis les millisecondes de 1 à 999
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET NOEXEC OFF
IF OBJECT_ID ('TEMPDB..#T1') IS NOT NULL
DROP TABLE #T1
CREATE TABLE #t1(the_date DATETIME2(3) NOT NULL PRIMARY KEY CLUSTERED )
GO
-- run this 999 times - hopefully there will be no duplicates
-- SELECT 204*24*60*60 - today is 23-july-2019 - the 203rd day of the year
DECLARE @DT DATETIME2(3)
SELECT @DT = CONVERT(DATETIME2(3),
DATEADD(SECOND, ABS(CHECKSUM(NEWID()) % 17625600),
'2019-01-01'),120)
--SELECT @DT
IF NOT EXISTS( SELECT 1 FROM #T1 WHERE THE_DATE = @DT)
INSERT INTO #T1 VALUES (@DT)
GO 999
--check it out what we have
SELECT * FROM #T1
--get the date and the new date
SELECT
THE_DATE
,THE_NEW_DATE= DATEADD(MILLISECOND, ROW_NUMBER() OVER (ORDER BY THE_DATE), THE_DATE )
FROM #T1
et voici ce que j'obtiens: (vue partielle)
L'une des autres affiches est correcte; DATETIME
(en T-SQL) n'est pas précis à la milliseconde (il est précis à la centiseconde).
Pour ce niveau de précision, vous souhaitez utiliser DATETIME2
.
Voici un exemple de conversion d'une chaîne datetime
en datetime2
, puis en ajoutant 1 milliseconde, et enfin, en reconvertissant en chaîne.
select convert(
varchar(MAX), --in T-SQL, varchar length is optional
dateadd(
millisecond,
1,
convert(
datetime2,
'2019-07-23 12:01:23.11'
)
)
)