SQL Server'da datetime zaman bölümünü kaldırmak için en iyi yaklaşım


514

Hangi yöntem SQL Server'da bir tarih saat alanından saat bölümünü kaldırırken en iyi performansı sağlar?

a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

veya

b) select cast(convert(char(11), getdate(), 113) as datetime)

İkinci yöntem, her iki yönde de birkaç bayt daha gönderir, ancak bu, dönüşüm hızı kadar önemli olmayabilir.

Her ikisi de çok hızlı görünüyor, ancak yüz binlerce veya daha fazla satırla uğraşırken hızda bir fark olabilir mi?

Ayrıca, SQL'de bir datetime zaman bölümü kurtulmak için daha iyi yöntemler olması mümkün mü?


1
Bunu üretim tablolarımdan birinde bir milyon kayıtta denedim ve her iki şekilde de performans hakkında doğru bir okuma alamadım. Her iki yöntem de aynı miktarda veri döndürdü.
Stephen Perelson

9
18.000.000 satırda bulduğum şey budur (SQL Server 2008): Yöntem b, yöntem a'dan yaklaşık% 24 daha yavaştır. CAST (KAT (DÖŞEME OLARAK (getdate)) DATETIME OLARAK) yöntem a'dan% 3,5 daha yavaştır. A yöntemi performans açısından bir kazanan gibi görünmektedir. Harika cevaplar için hepinize teşekkürler.
Stephen Perelson

46
Neden halt SQL zaten bunu yapmak için yerleşik bir işlevi yok? !!
Gary McGill

10
SQL 2008'in yeni DATE veri türü bunu ele alacaktır.
Philip Kelley

Yanıtlar:


558

Kesinlikle, yöntem aen az kaynak yoğun olan yöntemdir :

a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

Daha az CPU yoğun aynı toplam süre için bir milyon satır bazıları tarafından çok fazla zaman ellerinde: SQL Server'da tarih + saat tarih almak için en verimli yolu?

Başka yerlerde de benzer sonuçlarla benzer bir test gördüm.

Ben DATEADD / DATEDIFF tercih çünkü:

  • varchar dil / tarih biçimi konularına tabidir
    Örnek: CASE ifadem neden belirleyici değil?
  • şamandıra dahili depolamaya dayanır
  • "0" tabanını değiştirerek ayın ilk günü, yarın vb. çalışma süresini uzatır.

Düzenle, Eki 2011

SQL Server 2008+ için, dateyani CAST yapabilirsiniz CAST(getdate() AS date). Veya sadece dateveri türünü kullanın, böylece kaldırılacak zaman yok.

Edit, Oca 2012

Bunun ne kadar esnek olduğuna dair çalışılmış bir örnek: sql sunucusunda yuvarlanan zaman veya tarih rakamına göre hesaplanması gerekiyor

Edit, Mayıs 2012

Bunu WHERE deyimlerinde ve benzerlerinde düşünmeden kullanmayın: bir sütuna işlev veya CAST eklemek dizin kullanımını geçersiz kılar. Buradaki 2 numaraya bakın: http://www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/

Şimdi, bunun daha sonra bugüne kadar CAST'ı yöneten daha sonraki SQL Server optimiser sürümlerine bir örneği var, ancak genellikle kötü bir fikir olacak ...

, Nis 2018, datetime2 için

DECLARE @datetime2value datetime2 = '02180912 11:45' --this is deliberately within datetime2, year 0218
DECLARE @datetime2epoch datetime2 = '19000101'

select DATEADD(dd, DATEDIFF(dd, @datetime2epoch, @datetime2value), @datetime2epoch)

3
Ekim 2011 düzenlemesi için David Sopko sonra kod şöyle olurdu: select cast (tarih olarak GETDATE ())
Choco Smith

1
SQL'in daha yeni sürümleri için datetime yerine date kullanmak saatlerle uğraşma gereğini ortadan kaldırır. Aşağıdaki örneği kullanın: declare noTime date = getdate (), withTime datetime = getdate () select @ noTime, @ withTime
ozkary

1
sadece tarihe ihtiyacınız varsa tarih olarak döküm harika. Bununla birlikte, genellikle gece yarısı geçerli tarihe ihtiyacınız vardır, böylece daha fazla tarih manipülasyonu yapabilirsiniz. DATEveri zamanı, cihazın diğer tarih / saat veri türleri ile dateadd, DateDiff gibi şeyler bakımından ve etkileşim ile yapalım ne de obnoxiously kısıtlayıcı. Bu davalar için DATEADD()yaklaşım kralı yönetir.
Xedni

Bu her tarih için geçerli değildir. Yıl 0218yerine yanlışlıkla girmiştim 2018ve DATEDIFFThe conversion of a datetime2 data type to a datetime data type resulted in an out-of-range datetime valueselect DATEDIFF(dd, 0, convert(datetime2(0), '0218-09-12', 120))
ifadenizin

1
@ BernhardDöbler, Temmuz 2009'da "0218" yanıtını verdiğimde geçerli bir tarih olurdu, bu yüzden bu kadar uzağa gitmezdiniz. Ayrıca "0" datetime2 için 19000101 dönüştürmez. Bu seçimi deneyinSELECT DATEDIFF(dd, '19000101', convert(datetime2(0), '0218-09-12', 120))
gbn

69

SQL Server 2008'de şunları kullanabilirsiniz:

CONVERT(DATE, getdate(), 101)

13
Üçüncü argüman bir dönüştürme sonucunu kesinlikle hiçbir ilgisi yoktur datetimebir etmek date, ve solüsyon kadar etkili sadece aşağı kaynar CONVERT(DATE,getdate())zaten defadan fazla öne sürülmüştür ki,.
Andriy M

Sadece CAST(GETDATE() AS DATE)veya CAST(CURRENT_TIMESTAMP AS DATE)değersiz olduğunu düşündüğüm kesinlikle ANSI kullanın . Birincisi ile kalın.
Ivanzinho

52

Tabii ki bu eski bir iplik ama bunu tamamlamak için.

SQL 2008'den DATE veri türünü kullanabilirsiniz, böylece şunları yapabilirsiniz:

SELECT CONVERT(DATE,GETDATE())

21
SELECT CAST(FLOOR(CAST(getdate() AS FLOAT)) AS DATETIME)

... değil aşağıdaki yorumlara göre iyi bir çözüm .

Bu cevabı silebilirdim, ancak yorumcunun neden iyi bir fikir olmadığına dair açıklamasının hala yararlı olduğunu düşündüğüm için burada bir karşı örnek olarak bırakacağım .


GBN'nin cevabına bakın, çoğu bunu araştırdı. DATETIME, float olarak saklanmaz ve bu nedenle DATEADD / DATEDIFF kullanılması, türler arasında matematiksel manipülasyon ihtiyacını ortadan kaldırır.
MatBailie

Açıklamak için DATETIME FLOAT bir döküm kaçınmak isteyebilirsiniz kabul edebilir, ama bu durumda OPs seçeneği (a) sıfır örtük dönüşüm de bir sorun değil mi? Hmmm ... Sanırım bu durumda bir FLOAT değil ve sunucu muhtemelen zaman bilgisini atmak için yeterince akıllı. Tamam, kabul ediyorum :-)
Gary McGill

0 gerçekten sayısal bir türden (tahmin edeceğim INT) DATETIME'a örtük bir dönüşümdür. Ancak bu sürekli bir ifade olduğundan, optimize edici bunu Saklı Yordamlar için derleme zamanında yapabilir ve SQL'i dinamik olarak yürütmek için yalnızca bir kez yapması gerekir. Kısacası, bunun için bir kez ek yük vardır, FLOAT tabanlı sorgu her Satır için ek yüke sahiptir.
MatBailie

Şamandıra dökümü çok kesin değil. Bu cevap silinmelidir. Kimse bu kodu kullanmamalıdır.
usr

3
Şamandıraya dökülmenin ve datetime geri dönmenin güvenli olmadığından bahsetmiyorum - şamandıra yeterli hassasiyete sahip değil. Bu yüzden bence hiç tavsiye edilemez. Daha fazla ayrıntı için bu gönderiye bakın .
ErikE

17

SQL Server 2008'de, bir DATE veri türü (ayrıca bir TIME veri türü) vardır.

CAST(GetDate() as DATE)

veya

declare @Dt as DATE = GetDate()

Kullandığım bu ve iyi çalıştı. En basit cevap gibi görünüyor. CONVERT ile birlikte kullanımda herhangi bir olumsuzluk var mı?
joelmdev

1
CAST ve CONVERT işlev olarak eşdeğerdir. Fark, CAST'ın ANSI standardının bir parçası olması ve CONVERT'in T-SQL'e özgü olmasıdır. Bu nedenle, mümkün olan her yerde CAST kullanın.
Troy

@troy CAST kullanıyorum çünkü 3 yazım harfini kaydedebiliyorum ve sözdizimi
CONVERT'ten

8

İşte başka bir yinelenen sorudan başka bir cevap daha :

SELECT CAST(CAST(getutcdate() - 0.50000004 AS int) AS datetime) 

Bu sihirli sayı yöntemi DATEADD yönteminden biraz daha hızlı çalışır. (~% 10 gibi görünüyor)

Bir milyon kaydın birkaç turunda CPU Zamanı:

DATEADD   MAGIC FLOAT
500       453
453       360
375       375
406       360

Ancak, bu sayıların büyük olasılıkla alakasız olduğunu unutmayın, çünkü zaten ÇOK hızlıdırlar. 100.000 veya daha fazla kayıt kümem olmadıkça, CPU Zamanını sıfırın üzerinde okuyamazdım.

DateAdd'ın bu amaç için tasarlandığı ve daha sağlam olduğu düşünüldüğünde, DateAdd kullanın.


1
Bu korkunç. Verilerimi asla böyle riske atmam. Bunun sadece test ettikleriniz için değil, tüm tarihler için doğru olup olmadığını kim bilebilir .
usr

@usr Oh, doğru, bu sadece sihirli bir sayı ve bu nedenle kullanılmamalıdır. Doğruluğunu kontrol etmek istiyorsanız, bir gün için olası tüm tarihleri ​​bir tabloda doldurun ve sonuçları kontrol edin! Ayrıca daha fazla bilgi için bu gönderiye bakın .
ErikE

@ErikE iyi bir nokta. Cevabınız '12:00:00.003'daha iyi olduğunu düşündüğüm kullanımı mümkün kılıyor.
usr

6
SELECT CAST(CAST(GETDATE() AS DATE) AS DATETIME)

4
Geçerli bir seçenek, evet. Yine de, bu konuya birden fazla kez önerildi.
Andriy M

Dürüst olmak gerekirse, bu çözüm okunması en kolay olanıdır. My goto
BelgoCanadian

5

Gerçekten sevdim:

[date] = CONVERT(VARCHAR(10), GETDATE(), 120)

120Biçim kodu ISO 8601 standardına içine tarih zorlamak olacaktır:

'YYYY-MM-DD' or '2017-01-09'

Dplyr ( R) ve pandalarda ( Python) kullanımı çok kolay !


3

DİKKAT!

A) ve b) yöntemleri her zaman aynı çıktıya sahip DEĞİLDİR!

select DATEADD(dd, DATEDIFF(dd, 0, '2013-12-31 23:59:59.999'), 0)

Çıktı: 2014-01-01 00:00:00.000

select cast(convert(char(11), '2013-12-31 23:59:59.999', 113) as datetime)

Çıktı: 2013-12-31 00:00:00.000

(MS SQL Server 2005 ve 2008 R2 üzerinde test edilmiştir)

DÜZENLEME: Adem'in açıklamasına göre, tablodan tarih değerini okursanız bu gerçekleşemez, ancak tarih değerinizi bir değişmez değer olarak verirseniz (örnek: ADO.NET üzerinden saklanan yordamın bir parametresi olarak) olabilir.


1
.999 bir DATETIMEsütunda SQL Server'da depolanamaz . Mevcut en yüksek değer .997'dir. Kimden: msdn.microsoft.com/en-us/library/ms187819.aspx , değerlerin binde 0, 3 veya 7 olacak şekilde yuvarlandığını göreceksiniz. OP görmeyecek testlerindeki değerlerini tablolarında gösterir.
Adam Wenger

Haklısın. Bunu OP sorusuna bir cevap olarak göndermek istemedim, ancak başkalarının görmesi için bir yorum olarak, ancak sadece 11 itibar puanım vardı ve yorum yapmak için 15'e ihtiyacım var.
broslav

İlk snippet'inizde dize sabiti örtük olarak bir datetime dönüştürülür, ikincisinde bir dize kalır (ve 113 göz ardı edilir).
Andriy M

2

En başta kesici uçlarda / güncellemelerde zaman ayırın. Anında dönüşüme gelince, hiçbir şey kullanıcı tanımlı bir işlevi idame kabiliyeti açısından yenemez:

select date_only(dd)

Uygulaması date_onlyistediğiniz herhangi bir şey olabilir - şimdi soyutlanmış ve arama kodu çok daha temiz.


Bir keresinde seçilen sütunlardan süreleri fırçalamak için bir tetikleyici tasarladım. Veriler kötü olamazsa, temizlemeniz gerekmez.
Philip Kelley

2
UDF yaklaşımının bir dezavantajı var, SARGable değiller. JOIN veya WHERE yan tümcelerinde kullanılırsa, iyileştirici performansı artırmak için INDEX'leri kullanamaz. Ancak DATEADD / DATEDIFF yaklaşımını kullanmak SARGable'dır ve INDEX'lerden yararlanabilecektir. (Görünüşe göre FLOAT yöntemi de SARGable'dir)
MatBailie

1
@MatBailie Farklı olmak için yalvarıyorum! UDF'ler kesinlikle SARGable değildir, ancak Dateadd değildir ve Float'a dönüştürülmez! WHERE DateAdd(DateDiff(Column)) = @DateValuebir dizin kullanmaz. Öte yandan, WHERE Column >= dbo.UDF(@DateValue) AND Column < dbo.UDF(@DateValue + 1) bir SARGable. Bu yüzden nasıl koyduğunuza dikkat edin.
ErikE

2

Bu soruya bakın:
SQL Server'da bir tarih saatini nasıl kısaltabilirim?

Ne yaparsanız yapın , string yöntemini kullanmayın . Bu yapabileceğiniz en kötü yolla ilgili.


Teşekkürler, bunun daha önce sorulmuş olması gerektiğini düşündüm. Deneylerim tuhaf olsa da float yönteminin SQL Server 2008'de dateadd (dd, 0, tarihliiff (dd, 0, getDate ())) yönteminden% 3.5 daha yavaş olduğuna dikkat çekti. Her yöntem için testlerimi birçok kez çalıştırdım ve veritabanı sunucusu o zaman başka bir şey için kullanılmadı.
Stephen Perelson

Diyelim ki, işlerinin bir parçası olarak düzenli ve çok bilimsel bir şekilde kıyaslama yaptıklarını göstermemiş olan herkes tarafından yapılan kıyaslamalardan şüpheliyim. Thomas'ın gbn bağlantısındaki karşılaştırmasının bile baktığınızda bazı belirgin sorunları var. Bu mutlaka yanlış yapmaz, kesin değil. Döküm / zemin / döküm yöntemi, çok uzun bir süre için en hızlı kabul edilen yöntemdi ve bir zamanlar tartışılmaz bir şekilde doğru olduğundan şüpheleniyorum. Bununla birlikte, yeniden düşünmeye başladım; özellikle tamamen gereksiz olan sql server 2008 için.
Joel Coehoorn

1
String yönteminin kullanımı, okunması ve hatırlanması son derece kolaydır. Bunlar hafife aldığınızı düşündüğüm çok önemli faktörler!
Ben

1
@JoelCoehoorn, dönüştürme stili 121 "ODBC Kanonik" olarak adlandırılır. Harmanlama veya yerel ayarla değişmez. Yaylı numara, yıl, yıl + ay, gün, saat veya dakikaya genelleme yapmak da kolaydır.
Ben

1
@Ben: String trick, geliştiricilere string dönüşümlerini kullanmalarını öğretir. Onlar işe , ancak tarih matematik hız değil en az biri birçok nedenlerle, çok, çok üstün olduğunu - geliştirici tarihleri-as-sayılarla sağladığını çalışmak öğrenme ne daha ama ve onun zihinsel yetenekleri kodda sayı manipülasyonu ile akışkan olun.
ErikE

2

Zaten cevap verdim ama bunu da oraya atacağım ... bu sözde de iyi bir performans sergiliyor, ancak ondalık (zaman depolayan) şamandıradan atılarak ve sadece bütün parçayı (tarih olan) geri döndürerek çalışıyor

 CAST(
FLOOR( CAST( GETDATE() AS FLOAT ) )
AS DATETIME
)

ikinci kez bu çözümü buldum ... ben bu kodu kaptı


1
Şamandıraya dönüştürmek güvenli değildir .
ErikE

2
CAST(round(cast(getdate()as real),0,1) AS datetime)

Bu yöntem dize işlevini kullanmaz. Datetemelde ondalık basamaktan önceki basamaklı gerçek bir veri türüdür.

bu sanırım çok daha hızlı olacak.


1
Şamandıra olarak döküm güvenli değildir .
ErikE


2

CONVERT (karakter (10), GetDate (), 126) öğesini seçin


@ Broslav yanıtında veya olarak belirlenmiştir yönteminden söz yönteminden Öneriniz başlıca fark nedir yavaş içinde bu iş parçacığı (kabul edilen cevap aynı bağlantı)?
Andriy M

1

bence demek istedin ki cast(floor(cast(getdate()as float))as datetime)

gerçek sadece 32 bittir ve bazı bilgileri kaybedebilir

Bu en hızlı cast(cast(getdate()+x-0.5 as int)as datetime)

... sadece% 10 daha hızlı olsa da(about 0.49 microseconds CPU vs. 0.58)

Bu önerildi ve şu anda testimde aynı zamanı alıyor: DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

SQL 2008'de, SQL CLR işlevi, bir SQL işlevini kullanmaktan yaklaşık 5 kat daha hızlıdır, 1,35 mikrosaniyede 6,5 mikrona kadar, basit bir SQL UDF'ye karşı bir SQL CLR işlevi için çok daha düşük işlev çağrısı yükünü gösterir.

SQL 2005'te, SQL CLR işlevi, testime göre bu yavaş işleve göre 16 kat daha hızlıdır:

create function dateonly (  @dt datetime )
returns datetime
as
begin
return cast(floor(cast(@dt as float))as int)
end

1

Nasıl select cast(cast my_datetime_field as date) as datetime)? Bu, saat 00:00 olarak ayarlandığında aynı tarihle sonuçlanır, ancak metne dönüştürülmesini önler ve aynı zamanda açık sayısal yuvarlamayı da önler.



Aynı değiller. Diğer cevaplar , zaman bileşeni olmayan bir tarihe yayınlamayı ve böyle bırakmayı önerdi . Gönderim, gece yarısı saatiyle birlikte bir tarih saatine ayarlar. Büyük bir fark var; MS Excel'e aktarmayı deneyin ve tarih saatinden çok daha iyi işlediğini göreceksiniz.
Doktor Drew

İlki tamamen aynı.
Mikael Eriksson

Tamam, evet, şimdi görüyorum. Gerekirse cevabımı kopya olarak kaldırmaktan memnuniyet duyarım.
Dr. Drew

1

Bence kesinlikle buna sadık kalırsanız TSQL, zamanı kısaltmanın en hızlı yolu budur:

 select convert(datetime,convert(int,convert(float,[Modified])))

Bu kesme yöntemini yöntemden yaklaşık% 5 daha hızlı buldum DateAdd. Ve bu, en yakın güne yuvarlanacak şekilde kolayca değiştirilebilir:

select convert(datetime,ROUND(convert(float,[Modified]),0))

Şamandıraya dönüştürmek güvenli değildir .
ErikE

1

Burada SQL Server için datetime bazı bölümlerini kaldırmak için bir işlev yaptı. Kullanımı:

  • İlk param, sökülme tarihi.
  • İkinci parametre karakterdir:
    • s: saniye yuvarlar; milisaniyeyi kaldırır
    • m: dakikaya yuvarlar; saniye ve milisaniyeyi kaldırır
    • h: saate yuvarlar; dakika, saniye ve milisaniyeyi kaldırır.
    • d: güne yuvarlar; saat, dakika, saniye ve milisaniyeyi kaldırır.
  • Yeni tarih saatini döndürür

create function dbo.uf_RoundDateTime(@dt as datetime, @part as char) returns datetime as begin if CHARINDEX( @part, 'smhd',0) = 0 return @dt; return cast( Case @part when 's' then convert(varchar(19), @dt, 126) when 'm' then convert(varchar(17), @dt, 126) + '00' when 'h' then convert(varchar(14), @dt, 126) + '00:00' when 'd' then convert(varchar(14), @dt, 112) end as datetime ) end


Teşekkürler Andriy! Benim tavsiyem o kadar verimli değildi bilmiyordum. En azından işe yarıyor, ama haklısın.
Max Vargas

1

Yukarıdaki sürümlerin birçoğu işe yaramadığından birinin Sybase sürümünü araması durumunda

CAST(CONVERT(DATE,GETDATE(),103) AS DATETIME)
  • Adaptive Server 15.7 üzerinde çalışan I SQL v11'de test edildi

Bu, kabul edilen cevapta bir düzenleme olarak daha uygundur. Diğer 20 cevapla birlikte bu gömülecek ve neredeyse kullanılamayacak. Ayrıca kabul edilen cevap aşağıdakilerden de söz eder cast: SQL Server 2008+ için bugüne kadar CAST yapabilirsiniz. Ya da sadece tarihi kullanın, böylece kaldırılacak zaman yok.
EWit

Bunu eşdeğer bir Sybase sorusuna cevap olarak göndermek en iyisidir. Böyle bir soru yoksa, bir tane oluşturmakta özgürsünüz (ve kendiniz cevaplayabilirsiniz).
Andriy M

Bunun yanı sıra, bir dönüştürme zaman CONVERT üçüncü bir parametreyi belirtmek için anlamsızdır datetimeiçin date: ne olanların doğal bir biçimi vardır.
Andriy M

0

Mümkünse, bunun gibi özel şeyler için CLR işlevlerini kullanmayı seviyorum.

Bu durumda:

[Microsoft.SqlServer.Server.SqlFunction]
    public static SqlDateTime DateOnly(SqlDateTime input)
    {
        if (!input.IsNull)
        {
            SqlDateTime dt = new SqlDateTime(input.Value.Year, input.Value.Month, input.Value.Day, 0, 0, 0);

            return dt;
        }
        else
            return SqlDateTime.Null;
    }

0

Ben şahsen, SQL Server 2005 (veya daha düşük bir sürüm) ile uğraşırken bunun için neredeyse her zaman Kullanıcı Tanımlı işlevler kullanıyorum , ancak UDF'lerin kullanımının özellikle WHERE yan tümcelerine uygulanması durumunda belirli dezavantajlar olduğu belirtilmelidir (aşağıya bakın ve daha fazla ayrıntı için bu cevaba yapılan yorumlar). SQL Server 2008 (veya üstü) kullanıyorsanız - aşağıya bakın.

Aslında, oluşturduğum çoğu veritabanı için, bu UDF'leri başlangıçta hemen ekliyorum çünkü er ya da geç onlara ihtiyaç duyma şansımın% 99 olduğunu biliyorum.

Ben "sadece tarih" ve "sadece zaman" için bir tane oluşturmak ("sadece tarih" biri ikisinin en çok kullanılan olmasına rağmen).

İşte tarihle ilgili çeşitli UDF'lere bazı bağlantılar:

Temel SQL Server Tarih, Saat ve DateTime İşlevleri
Yalnızca Tarih Alma İşlevi

Bu son bağlantı, tarihi bir datetime alanının yalnızca bir parçası olarak almanın en az 3 farklı yolunu gösterir ve her yaklaşımın bazı artılarını ve eksilerini belirtir.

Bir UDF kullanılıyorsa, sorguda WHERE yan tümcesinin bir parçası olarak UDF'yi kullanmaktan kaçınmaya çalışmalısınız, çünkü bu sorgu performansını büyük ölçüde engelleyecektir. Bunun temel nedeni, bir WHERE yan tümcesinde bir UDF kullanmanın bu yan tümceyi anlaşılmaz kılmasıdır . UDF'leri kendi kullanımımla ilgili olarak, WHERE yan tümcesinde "raw" tarih sütununu sık sık kullanacağım, ancak UDF'yi SELECTed sütununa uygulayacağım. Bu şekilde, UDF sadece filtrelenen sonuç kümesine uygulanır ve tablonun her satırına filtrenin bir parçası olarak uygulanmaz.

Tabii ki, bunun için mutlak en iyi yaklaşım SQL Server 2008 (veya daha yüksek) kullanmak ve tarih ve saatlerinizi ayırmaktır , çünkü SQL Server veritabanı motoru daha sonra yerel olarak tarih ve saat bileşenlerini sağlar ve bunları bağımsız olarak etkin bir şekilde sorgulayabilir tarih veya saat parçasını bileşik tarih-saat türünden ayıklamak için bir UDF veya başka bir mekanizmaya gerek kalmadan.


UDF kullanmak bazı durumlarda iyi olabilir (parametreleri fırçalarken olduğu gibi). Ancak çoğu durumda bu korkunç bir çözümdür - her satır için bir kez UDF çalıştırmak bir sorgunun performansını herhangi bir ihtiyaç olmadan öldürmenin bir yoludur !
ErikE

@ErikE - Katılmıyorum, Erik, UDF'ler performans katilleridir, bu yüzden SQL Server 2008 veya üstünü kullanabilir ve bunu sizin için yapan yerleşik bir veri türü kullanırsanız, bunun en iyi çözüm olacağını söylüyorum. (gerekeni başarmak hem de performans açısından). SQL Server'ın yerel olarak bunu desteklemeyen eski bir sürümü ile sıkışmışsanız , gereksinimlerinize ulaşmak için bir şeyden vazgeçeceksiniz .
CraigTP

Doğru. Veritabanı motoru bize SARGable olan, ancak daha kolay ifade edilebilen bir şey verse iyi olurdu. Eğer bütün bir gün boyunca herhangi bir zamanda var bir değere arıyorsanız arada, bu hala (SQL en azından eski sürümleri için) en iyi çözümdür: WHERE DateColumn >= {TimeTruncatingExpression}(@DateValue) AND DateColumn < {TimeTruncatingExpression}(@DateValue + 1). "Neredeyse her zaman UDF kullanıyorum" dediğinden beri bir şey söylemem gerektiğini hissettim.
ErikE

@ErikE - Endişelenme, Erik. UDF'leri kullandığımda, performansın çok önemli olmadığı küçük veri kümeleriyle çalışıyorum veya daha büyük olasılıkla sorguyu "ham" tarih alanına göre filtreliyorum (anlaşılabilirliği sağlamak için), ancak sütunu seçiyorum UDF uygulanır. Bunlar genellikle filtrelendikten sonra küçük veri kümeleri olduğundan, UDF'yi bu az sayıda kayıt üzerinde çalıştırmak böyle bir performans isabeti değildir. Bununla birlikte, çok iyi bir noktaya değindin ve cevabımı bunu yansıtacak şekilde güncelledim.
CraigTP

-4

Kullanmak istiyorum:

CAST
(
CAST(YEAR(DATEFIELD) as varchar(4)) + '/' CAST(MM(DATEFIELD) as varchar(2)) + '/' CAST(DD(DATEFIELD) as varchar(2)) as datetime
) 

Böylece etkili bir şekilde sahip olduğunuz tarih alanından yeni bir alan oluşturma.


2
Neden bunu yapasın? Bir datetimedeğerden bitleri ayıklamanın , dizelere dönüştürmenin, bunları bir araya getirmenin ve sonucu tekrar geri dönüştürmenin, datetimeörneğin orijinalde datetime( DATEADD/ DATEDIFFyöntemi) doğrudan hesaplamalar yapmaktan daha iyi olduğunu düşünüyor musunuz?
Andriy M

Ayrıca, nedir MMve DD? SQL Server'da böyle bir işlev yoktur.
Andriy M
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.