2011-09-13 27 views
5

Có thể viết truy vấn Microsoft SQL sẽ nhóm theo kiểu dữ liệu datetime nhưng bỏ qua phần thời gian chẳng hạn như giờ và phút?Nhóm theo datetime bỏ qua phần thời gian

+2

Phiên bản SQL Server nào? Nó không quan trọng cho câu hỏi cụ thể này. (nó là * có thể * trong tất cả các phiên bản của SQL Server, nhưng có một giải pháp tốt hơn trong năm 2008 +) – RBarryYoung

+0

có thể trùng lặp của [Làm thế nào để cắt bớt một datetime trong SQL Server] (http://stackoverflow.com/questions/923295/ làm thế nào để truncate-a-datetime-in-sql-server) và [nhiều người khác] (http://www.google.com/cse?cx=018205968162215846785%3A7n6ajnwyz-i&ie=UTF-8&q=sql+server+ truncate +% 28datetime | time% 29 & sa = Tìm kiếm & siteurl = www.google.com% 2Fcse% 2Fhome% 3Fcx% 3D018205968162215846785% 3A7n6ajnwyz-i) –

+1

@AndriyM - Nhóm theo phần 'ngày' của' datetime' trình bày một vấn đề tối ưu hóa cụ thể ngoài việc cắt ngắn phần ngày mặc dù. ví dụ. so sánh các kế hoạch cho 'TẠO TẠO T1 (D DATETIME2 PRIMARY KEY); TẠO TABLE T2 (D NGÀY, T THỜI GIAN, CHÍNH CHÍNH (D, T)); CHỌN COUNT (*) TỪ TÊN TÊN T1 B CANG CAST (D NHƯ NGÀY) TÙY CHỌN CHỌN COUNT (*) TỪ NHÓM TÓM TẮT TÊN TÙY CHỌN (TÊN ĐẶT HÀNG) ' –

Trả lời

12

Nếu bạn đang sử dụng SQL Server 2008, điều này rất đơn giản.

GROUP BY CAST(YourCol AS Date) 

Đối với các phiên bản trước, bạn có thể sử dụng

GROUP BY DATEDIFF(DAY, 0, YourCol) 

Tuy nhiên không ai trong số này sẽ có thể tận dụng thực tế là một chỉ mục trên YourCol mà được sắp xếp theo datetime cũng sẽ được sắp xếp theo date và do đó sử dụng luồng tổng hợp mà không có thao tác sắp xếp.

Trên SQL Server 2008+ bạn có thể xem xét lập chỉ mục (date,time) thay vì datetime để tạo điều kiện cho loại truy vấn này. Hoặc đơn giản là lưu trữ nó dưới dạng hai thành phần riêng biệt và có thể cung cấp cột được tính toán để tái kết hợp các bộ phận (datetime2 được lưu giữ giống như datetime. cột đẩy NULL_BITMAP lên một byte mới.).

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

Hoặc cách khác, bạn có thể lưu trữ kết hợp trong bảng cơ sở và sử dụng các chỉ mục được sử dụng để tách nó ra.

Một ví dụ của phương pháp này

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

'GROUP BY DATEDIFF (DAY, 0, YourCol)' có lẽ cũng đủ trong trường hợp này ... – Tomalak

+0

@Tomalak - Good point. Điều đó sẽ trả về 'int' đủ để' nhóm bởi' và không có lý do nào để chuyển đổi về 'datetime' ngoại trừ mục đích hiển thị. –

1

Nếu bạn có một bảng lớn và muốn nhóm để xảy ra nhanh, bạn không thể dựa vào nhóm một biểu thức.

Tạo một cột datetime thêm trên bàn của bạn và nó có đầy bởi một nút bấm cho phép tính ngày cơ sở của bạn "thật" date:

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

Sau đó đặt một chỉ mục trên EffectiveDate và nhóm (và tìm kiếm) sẽ nhanh hơn rất nhiều.

+0

Đối với SQL Server 2008 truyền theo ngày [là sargable] (http://connect.microsoft.com/SQLServer/feedback/details/526431/make-more-functions-sargable) mặc dù tôi đã không kiểm tra xem điều này có được thừa hưởng trong truy vấn 'nhóm bởi'. –

+0

@Martin Thú vị, tôi không biết điều đó. Nhưng nó vẫn sẽ kích hoạt một bảng quét khi không có chỉ số trên cột, phải không? – Tomalak

+0

Tại sao kích hoạt và không phải là cột được tính? 'EffectiveDate AS CONVERT (DATETIME, DATEADD (DAY, 0, DATEDIFF (DAY, 0, t.RecordDate)))' - cột này có thể được duy trì và lập chỉ mục cũng như loại bỏ bất kỳ nghi ngờ nào về sargability, mà không phải trả phí cò súng. –

Các vấn đề liên quan