Bir datetime dizesine 1 milisaniye nasıl eklenir?


15

Bir seçime dayanarak, böyle x satır döndürebilirim:

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

0 ile tüm milisaniye var.

1 x 1 milisaniye eklemenin bir yolu var mı, bu yüzden seçim şöyle görünür:

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

Başarısız bir imleç ve hatta güncelleme oluşturmaya çalışıyorum.

Bu istediğim sonuçları almak için sorgu:

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

81k değer vardır. Alan DATETIME.


2
Sıra 1'e 1 milisaniye, sıra 2'ye 2 milisaniye, sıra 3'e 3 milisaniye eklemeye mi çalışıyorsunuz?
John Eisbrener

Yanıtlar:


33

Datetime1 milisaniye düzeyine kadar kesin değildir. Farklı bir veri türüne (yani datetime2) geçmediğiniz sürece istediğiniz şey mümkün değildir .

belgeleme

Önemli teklif:

Doğruluk .000, .003 veya .007 saniyelik artışlara yuvarlanır


13

DateAddFonksiyon aradığınız budur.

millisecondMilisaniye eklediğinizi belirtmek için işleve ilk parametre olarak kullanın . Ardından 1, eklenecek milisaniye sayısı için ikinci parametre olarak kullanın .

Burada, geçerli saati bir değişkene alıp ona bir milisaniye ekleyip sonucu ikinci bir değişken olarak kaydedip her değişkeni yazdırmak için bir örnek

Declare @RightNow as DateTime2
Declare @RightNowPlusAMillisecond as DateTime2

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

Print @RightNow
Print @RightNowPlusAMillisecond

Sonuçlar:

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

Not:

Forrest'in başka bir cevapta belirttiği gibi, datetimeveri türü milisaniye hassasiyetini garanti etmez. .000, .003 veya .007 saniyelik artışlarla yuvarlar. Milisaniye hassasiyet istiyorsanız, kullanın datetime2.


13

@ Doug-Deden doğru başlangıç ​​noktasına sahip, ama sadece sorunun asıl niyeti olduğunu düşündüğüm yanıtı - satır başına milisaniye artan bir sonuç kümesine nasıl uygulayacağımı cevaplamak istedim.

Bu durumda, ROW_NUMBER ve bir Ortak Tablo İfadesi kullanabilirsiniz (birleşimler vb. Dahil olmak üzere tablo yapınız için gerektiği şekilde düzenleyin).

Değerleri göstermek için seçin:

;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

Güncelleme orijinal tabloya geri eklenir:

;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

Bu CTE güncellenebilir. Tekrar katılmanıza gerek yok Table1. Just doUPDATE CTE SET my_date_column =...
Steven Hibble

4

Bunu kullanarak yaptım DATETIME2(3).

Aşağıdaki sorguda gördüğünüz gibi, daha fazlası 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)

resim açıklamasını buraya girin

Arasındaki farklar datetimeve datetime2iyi açıklanmıştır burada .

Bu alıştırma için ben test amaçlı geçici bir tablo oluşturmak ve 999 farklı ile doldurmak random datesgelen 01-jan-2019(ve bugün 23-july-2019)

ve sonra sırayla, milisaniyeyi 1'den 999'a ayarladım

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

ve bunu elde ederim: (kısmi görünüm)

resim açıklamasını buraya girin


2

Diğer posterlerden biri doğrudur; DATETIME(T-SQL'de) milisaniye için doğru değildir (santisaniye için doğrudur).

Bu doğruluk seviyesi için kullanmak istersiniz DATETIME2.

İşte bir dize dönüştürme örneğidir datetimeiçin datetime2, sonra 1 milisaniye ekleme ve son olarak, bir dizeye geri dönüştürülmesi.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.