2011-09-13 20 views
5

datetime veri türüyle gruplanacak ancak saat ve dakika gibi zaman bölümünü göz ardı edecek bir Microsoft SQL sorgusu yazmak mümkün mü?Grup tarafından datetime zaman bölümünü yok sayılıyor

+2

Hangi SQL Server sürümü? Bu özel soru için önemli. (SQL Server'ın tüm sürümlerinde * mümkündür *, ancak daha iyi bir çözüm var 2008+) – RBarryYoung

+0

olası bir kopyası [SQL Server'da datetime nasıl kırpılır] (http://stackoverflow.com/questions/923295/ truncate-a-datetime-in-sql-server) ve [diğerleri] (http://www.google.com/cse?cx=018205968162215846785%3A7n6ajnwyz-i&ie=UTF-8&q=sql+server+ truncate +% 28datetime | time% 29 & sa = Ara & siteurl = www.google.com% 2Fcse% 2Fhome% 3Fcx% 3D018205968162215846785% 3A7n6ajnwyz-i) –

+1

@AndriyM - Bir 'datetime' tarihinin parçası tarafından gruplandırma belirli bir optimizasyon problemi sunar Tarih bölümünün sadece kesilmesinin ötesinde. Örneğin. CREATE TABLE T1 (D DATETIME2 PRIMARY ANAHTAR) için CREATE TABLE T2 (D TARİH, T TIME, PRİMARY ANAHTAR (D, T)) için planları karşılaştırmak; T1 GRUP TARAFINDAN DÖNÜŞÜMÜ (* DATE) SEÇENEĞİ (SİPARİŞ GRUBU); T2 GRUBUNUN TARAFINDAN SEÇENEĞİ SAYFASI (SİPARİŞ GRUBU) ' –

cevap

12

SQL Server 2008 kullanıyorsanız, bu basittir. Bunlardan hiçbiri datetime tarafından sipariş edilir YourCol üzerinde bir dizin de kullanmak böylece date tarafından sipariş edilecek ve gerçeğini kaldıraç mümkün olacak Ancak

GROUP BY CAST(YourCol AS Date) 

önceki sürümleri için,

GROUP BY DATEDIFF(DAY, 0, YourCol) 

kullanabilirsiniz sıralama işlemi olmayan bir akış toplaması.

SQL Server 2008+'de, bu tür sorgulamayı kolaylaştırmak için datetime yerine (date,time) dizinini kullanmayı düşünebilirsiniz.

ya sadece iki ayrı bileşen olarak depolamak ve muhtemelen parçaları birleşir hesaplanmış bir sütun sağlayan (a datetime2 bir date aynı saklanır ve bir time bu ek ise dışında herhangi bir fazla boşluk tüketmek olmaz sütun NULL_BITMAP yeni bir bayt üzerine iter.).

CREATE TABLE T 
(
YourDateCol date, 
YourTimeCol time, 
YourDateTimeCol AS DATEADD(day, 
          DATEDIFF(DAY,0,YourDateCol), 
          CAST(YourTimeCol AS DATETIME2(7))) 
/*Other Columns*/ 
) 

Veya alternatif bunun temel tabloda birleştirilir ve depolayabilir endeksleri dışarı ayrıldı hesaplanan sütunları kullanın var.

Büyük bir tablo var ve hızlı gerçekleşmesi gruplandırma istediğiniz takdirde bu yaklaşım

CREATE TABLE T 
(
DT DATETIME2, 
D AS CAST(DT AS DATE), 
T AS CAST(DT AS TIME) 
) 

CREATE INDEX IX1 ON T(DT); 

SELECT COUNT(*), 
     CAST(DT AS DATE) 
FROM T 
GROUP BY CAST(DT AS DATE) 

CREATE INDEX IX2 ON T(D,T); 

SELECT COUNT(*), 
     CAST(DT AS DATE) 
FROM T 
GROUP BY CAST(DT AS DATE) 

DROP TABLE T 

enter image description here

+3

'GRUP BY DATEDIFF (GÜN, 0, YourCol)' da muhtemelen bu durumda yeterli olacaktır ... – Tomalak

+0

@Tomalak - İyi nokta. Bu, "grup" için "int" olan ve görüntüleme amaçları haricinde "datetime" a dönme nedeni olmayan bir "int" döndürecektir. –

1

bir örneği, bir ifadeye gruplandırma güvenir olamaz.

UPDATE 
    MyTable 
SET 
    EffectiveDate = DATEADD(DAY, 0, DATEDIFF(DAY, 0, t.RecordDate)) 
FROM 
    MyTable t 
    INNER JOIN inserted i ON i.RowID = t.RowID 

Sonra EffectiveDate üzerinde bir dizin koymak ve gruplama (ve arama):

masanızdaki ek bir datetime sütunu oluşturun ve bunu "gerçek" tarihinden itibaren baz tarihini hesaplayan bir tetikleyici ile doldurduktan çok daha hızlı olacak.

+0

SQL Server 2008 için döküm [tarihçe sarj edilebilir] (http://connect.microsoft.com/SQLServer/feedback/details/526431/make-more-functions-sargable) bunun kaldırılıp kaldırılmadığını kontrol etmedim '' grup sorguları ile gruplandır. –

+0

@Martin İlginç, bunu bilmiyordum. Ancak, sütun üzerinde indeks olmadığında hala bir tablo taraması tetiklenir, değil mi? – Tomalak

+0

Neden bir tetikleyici ve hesaplanmış bir sütun değil? CONVERT (DATETIME, DATEADD (GÜNDÜZ, 0, DATEDIFF (GÜN, 0, t.RecordDate)))) - Bu sütun sarsılabilirlik ile ilgili herhangi bir şüphe çıkarmak için de kalıcı ve endeksli olabilir. tetik. –

İlgili konular