it-swarm-eu.dev

Jak dodać 1 milisekundę do ciągu datetime?

Na podstawie zaznaczenia mogę zwrócić x wierszy w następujący sposób:

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

Wszystkie milisekundy mają 0.

Czy istnieje sposób na dodanie 1 na 1 milisekundę, więc zaznaczenie wyglądałoby tak:

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

Próbuję utworzyć kursor, a nawet aktualizację bez powodzenia.

To jest zapytanie, aby uzyskać pożądane wyniki:

  select top 10 ModifiedOn 
    from [SCHEMA].[dbo].[TABLE]
  where FIELD between '2019-07-23 00:00' and '2019-07-23 23:59'

Jest 81k wartości. Pole to DATETIME.

15
Racer SQL

Datetime nie jest dokładny do poziomu 1 milisekundy. To, o co prosisz, nie jest możliwe, chyba że zmienisz inny typ danych (tj. datetime2).

Dokumentacja

Ważny cytat:

Dokładność Zaokrąglona do przyrostów 0,000, 0,003 lub 0,007 sekundy

33
Forrest

Funkcja DateAdd jest tym, czego szukasz.

Użyj millisecond jako pierwszego parametru do funkcji, aby powiedzieć jej, że dodajesz milisekundy. Następnie użyj 1 jako drugi parametr, dla liczby milisekund do dodania.

Oto przykład, pobieranie bieżącego czasu do zmiennej, a następnie dodawanie do niego jednej milisekundy i zapisywanie wyniku jako drugiej zmiennej, a następnie drukowanie każdej zmiennej

Declare @RightNow as DateTime2
Declare @RightNowPlusAMillisecond as DateTime2

Select @RightNow = Getdate()
Select @RightNowPlusAMillisecond = DateAdd(millisecond,1,@RightNow)

Print @RightNow
Print @RightNowPlusAMillisecond

Wyniki:

2019-07-23 08:25:38.3500000
2019-07-23 08:25:38.3510000

Uwaga:

Jak Forrest wskazuje w innej odpowiedzi, typ danych datetime nie gwarantuje precyzji w milisekundach. Zaokrągla to z dokładnością do 0,000, 0,003 lub 0,007 sekundy. Jeśli chcesz milisekundową precyzję, użyj datetime2.

13
Doug Deden

@ Doug-Deden ma właściwy punkt początkowy, ale chciałem tylko spróbować odpowiedzieć na to, co moim zdaniem było pierwotnym zamiarem pytania - jak zastosować je do zestawu wyników ze zwiększającą się milisekundą na wiersz.

W takim przypadku możesz użyć ROW_NUMBER i Common Table Expression (edytuj w razie potrzeby dla twojej struktury tabeli, włączając sprzężenia itp.).

Wybierz, aby wyświetlić wartości:

;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

Aktualizacja łączy ponownie do oryginalnej tabeli:

;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
13
BlueGI

Zrobiłem to za pomocą DATETIME2(3).

Jak widać na poniższym zapytaniu, jest to bardziej 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)

enter image description here

Różnice między datetime a datetime2 są dobrze wyjaśnione tutaj .

W tym ćwiczeniu tworzę tabelę tymczasową do celów testowych i wypełniam ją 999 różnymi random dates od 01-jan-2019 i dzisiaj (23-july-2019)

a następnie w kolejności ustawiam milisekundy od 1 do 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

i oto co otrzymuję: (częściowy widok)

enter image description here

4

Jeden z pozostałych plakatów jest poprawny; DATETIME (w T-SQL) nie jest dokładny do milisekundy (jest dokładny do centisekundy).

Dla tego poziomu dokładności chcesz użyć DATETIME2.

Oto przykład konwersji ciągu datetime na datetime2, a następnie dodanie 1 milisekundy i na koniec konwersja z powrotem na ciąg.

select convert(
            varchar(MAX), --in T-SQL, varchar length is optional
            dateadd(
                millisecond,
                1,
                convert(
                    datetime2,
                    '2019-07-23 12:01:23.11'
                )
            )
        )
2