it-swarm.com.de

Wie füge ich einer Datums- / Uhrzeitzeichenfolge 1 Millisekunde hinzu?

Basierend auf einer Auswahl kann ich x Zeilen wie folgt zurückgeben:

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

Wir haben alle Millisekunden mit 0.

Gibt es eine Möglichkeit, 1 x 1 Millisekunden hinzuzufügen, sodass die Auswahl folgendermaßen aussehen würde:

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

Ich versuche, einen Cursor oder sogar ein Update ohne Erfolg zu erstellen.

Dies ist die Abfrage, um die gewünschten Ergebnisse zu erhalten:

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

Es gibt 81k Werte. Das Feld ist DATETIME.

15
Racer SQL

Datetime ist nicht auf 1 Millisekunde genau. Was Sie verlangen, ist nur möglich, wenn Sie zu einem anderen Datentyp wechseln (d. H. datetime2).

Dokumentation

Wichtiges Zitat:

Genauigkeit Auf Schritte von .000, .003 oder .007 Sekunden gerundet

33
Forrest

Die Funktion DateAdd ist genau das, wonach Sie suchen.

Verwenden Sie millisecond als ersten Parameter für die Funktion, um anzuzeigen, dass Sie Millisekunden hinzufügen. Dann benutze 1 als zweiter Parameter für die Anzahl der hinzuzufügenden Millisekunden.

Hier ist ein Beispiel: Erfassen Sie die aktuelle Zeit in einer Variablen, fügen Sie eine Millisekunde hinzu, speichern Sie das Ergebnis als zweite Variable und drucken Sie dann jede Variable

Declare @RightNow as DateTime2
Declare @RightNowPlusAMillisecond as DateTime2

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

Print @RightNow
Print @RightNowPlusAMillisecond

Ergebnisse:

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

Hinweis:

Wie Forrest in einer anderen Antwort ausführt, garantiert der Datentyp datetime keine Millisekundengenauigkeit. Es wird in Schritten von .000, .003 oder .007 Sekunden gerundet. Wenn Sie eine Millisekundengenauigkeit wünschen, verwenden Sie datetime2.

13
Doug Deden

@ Doug-Deden hat den richtigen Ausgangspunkt, aber ich wollte nur versuchen zu beantworten, was meiner Meinung nach die ursprüngliche Absicht der Frage war - wie man sie auf eine Ergebnismenge mit zunehmenden Millisekunden pro Zeile anwendet.

In diesem Fall können Sie ROW_NUMBER und Common Table Expression verwenden (nach Bedarf für Ihre Tabellenstruktur bearbeiten, einschließlich Joins usw.).

Wählen Sie diese Option, um Werte anzuzeigen:

;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

Update verbindet sich wieder mit der ursprünglichen Tabelle:

;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

Ich habe es mit DATETIME2(3) gemacht.

Wie Sie in der folgenden Abfrage sehen können, ist es mehr 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

Die Unterschiede zwischen datetime und datetime2 sind gut erklärt hier .

Für diese Übung erstelle ich zu Testzwecken eine temporäre Tabelle und fülle sie mit 999 verschiedenen random dates von 01-jan-2019 und heute (23-july-2019)

und dann stelle ich in der richtigen Reihenfolge die Millisekunden von 1 bis 999 ein

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

und das bekomme ich: (Teilansicht)

(enter image description here

4

Eines der anderen Poster ist korrekt; DATETIME (in T-SQL) ist nicht millisekundengenau (genau in Centisekunden).

Für diese Genauigkeit möchten Sie DATETIME2 Verwenden.

Hier ist ein Beispiel für das Konvertieren eines Strings datetime in datetime2, Das Hinzufügen von 1 Millisekunde und schließlich das Zurückkonvertieren in einen String.

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