Bagaimana cara menambahkan 1 milidetik ke string datetime?

15

Berdasarkan pilih, saya dapat mengembalikan x baris seperti ini:

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

Kami memiliki semua milidetik dengan 0.

Apakah ada cara untuk menambahkan 1 oleh 1 milidetik, sehingga pilih akan terlihat seperti ini:

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

Saya mencoba membuat kursor atau bahkan pembaruan tanpa hasil.

Ini permintaan untuk mendapatkan hasil yang saya inginkan:

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

Ada nilai 81k. Lapangan adalah DATETIME.

SQL pembalap
sumber
2
Apakah Anda mencoba menambahkan 1 milidetik ke baris 1, 2 milidetik ke baris 2, 3 milidetik ke baris 3, dll?
John Eisbrener

Jawaban:

33

Datetimetidak tepat ke level 1 milidetik. Apa yang Anda minta tidak mungkin kecuali Anda mengubah ke tipe data yang berbeda (yaitu datetime2).

Dokumentasi

Kutipan penting:

Akurasi Membulatkan ke peningkatan 0,000, 0,003, atau 0,007 detik

Forrest
sumber
13

The DateAddFungsi adalah apa yang Anda cari.

Gunakan millisecondsebagai parameter pertama pada fungsi, untuk memberi tahu Anda menambahkan milidetik. Kemudian gunakan 1sebagai parameter kedua, untuk menambahkan jumlah milidetik.

Berikut ini sebuah contoh, mengambil waktu saat ini menjadi variabel, dan kemudian menambahkan satu milidetik ke dalamnya dan menyimpan hasilnya sebagai variabel kedua, dan kemudian mencetak setiap variabel

Declare @RightNow as DateTime2
Declare @RightNowPlusAMillisecond as DateTime2

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

Print @RightNow
Print @RightNowPlusAMillisecond

Hasil:

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

catatan:

Seperti yang ditunjukkan Forrest dalam jawaban lain, datetimetipe data tidak menjamin ketepatan milidetik. Itu membulatkan ke peningkatan .000, .003, atau .007 detik. Jika Anda ingin presisi milidetik, gunakan datetime2.

Doug Deden
sumber
13

@ Doug-Deden memiliki titik awal yang tepat, tetapi saya hanya ingin mencoba menjawab apa yang saya pikir adalah maksud asli dari pertanyaan - bagaimana menerapkannya pada hasil yang ditetapkan dengan peningkatan milidetik per baris.

Dalam hal ini, Anda dapat menggunakan ROW_NUMBER dan Common Table Expression (edit sesuai kebutuhan untuk struktur tabel Anda, termasuk gabungan, dll.).

Pilih untuk menunjukkan nilai:

;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

Pembaruan bergabung kembali ke tabel asli:

;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
BlueGI
sumber
CTE ini dapat diperbarui. Tidak perlu bergabung kembali ke Table1. Lakukan sajaUPDATE CTE SET my_date_column =...
Steven Hibble
4

Saya telah melakukannya menggunakan DATETIME2(3).

Seperti yang Anda lihat pada kueri di bawah ini, lebih dari itu 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)

masukkan deskripsi gambar di sini

Perbedaan antara datetimedan datetime2dijelaskan dengan baik di sini .

Untuk latihan ini saya membuat tabel temp untuk tujuan pengujian, dan mengisinya dengan 999 berbeda random datesdari 01-jan-2019dan hari ini ( 23-july-2019)

dan kemudian, saya mengatur milidetik dari 1 hingga 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

dan inilah yang saya dapatkan: (tampilan sebagian)

masukkan deskripsi gambar di sini

Marcello Miorelli
sumber
2

Salah satu poster lainnya benar; DATETIME(dalam T-SQL) tidak akurat hingga milidetik (akurat ke centisecond).

Untuk tingkat keakuratan itu, Anda ingin menggunakannya DATETIME2.

Berikut adalah contoh dari mengkonversi string datetimeke datetime2, kemudian menambahkan 1 milidetik, dan terakhir, mengkonversi kembali ke string.

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