2009-02-26 34 views
5

Tôi đang sử dụng MS SQL Server nhưng chào đón các giải pháp so sánh từ các cơ sở dữ liệu khác.Làm cách nào để bao gồm các hàng trống trong một truy vấn SQL GROUP BY DAY (date_field) duy nhất?

Đây là hình thức cơ bản của truy vấn của tôi. Nó trả về số lượng các cuộc gọi mỗi ngày từ 'incidentsm1' bảng:

SELECT 
    COUNT(*) AS "Calls", 
    MAX(open_time), 
    open_day 
FROM 
    (
SELECT 
incident_id, 
opened_by, 
open_time - (9.0/24) AS open_time, 
DATEPART(dd, (open_time-(9.0/24))) AS open_day 
    FROM incidentsm1 
    WHERE 
DATEDIFF(DAY, open_time-(9.0/24), GETDATE())< 7 

) inc1 
GROUP BY open_day 

Những thông tin này được sử dụng để vẽ một biểu đồ hình cột, nhưng nếu không có cuộc gọi trên một ngày nhất định trong tuần, có kết quả không hàng và do đó không có thanh, và người dùng là như thế, "tại sao đồ thị chỉ có sáu ngày và bỏ qua từ thứ bảy đến thứ hai?"

Bằng cách nào đó, tôi cần UNION ALL với một hàng trống từ mỗi ngày hoặc một cái gì đó tương tự, nhưng tôi không thể tìm ra.

Tôi bị ràng buộc với những gì tôi có thể làm với một câu lệnh SQL và tôi có quyền truy cập chỉ đọc vì vậy tôi không thể tạo bảng tạm thời hoặc bất kỳ thứ gì.

+0

Chỉ cần thêm nó trong lớp giao diện người dùng của bạn. http://stackoverflow.com/questions/346659/what-are-the-most-common-sql-anti-patterns/346850#346850 –

+0

xin lỗi, tôi sẽ, nhưng không thể với công cụ thương mại ưa thích mà tôi được yêu cầu sử dụng. – Nathan

Trả lời

7

Làm thế nào về một cái gì đó như thế này?

SELECT 
    COUNT(incident_id) AS "Calls", 
    MAX(open_time), 
    days.open_day 
FROM 
(
    select datepart(dd,dateadd(day,-6,getdate())) as open_day union 
    select datepart(dd,dateadd(day,-5,getdate())) as open_day union 
    select datepart(dd,dateadd(day,-4,getdate())) as open_day union 
    select datepart(dd,dateadd(day,-3,getdate())) as open_day union 
    select datepart(dd,dateadd(day,-2,getdate())) as open_day union 
    select datepart(dd,dateadd(day,-1,getdate())) as open_day union 
    select datepart(dd,dateadd(day, 0,getdate())) as open_day 
) days 
left join 
(
SELECT 
    incident_id, 
    opened_by, 
    open_time - (9.0/24) AS open_time, 
    DATEPART(dd, (open_time-(9.0/24))) AS open_day 
FROM incidentsm1 
WHERE DATEDIFF(DAY, open_time-(9.0/24), GETDATE()) < 7 
) inc1 ON days.open_day = incidents.open_day 
GROUP BY days.open_day 

Tôi chỉ thử nghiệm nó trên giản đồ bảng đơn giản, nhưng tôi nghĩ nó sẽ hoạt động. Bạn có thể cần phải tinker với các công cụ dateadd ..

+0

CẢM ƠN BẠN! Tôi đã hy vọng cho một cái gì đó loopish hơn nhưng tôi có thể dạ dày 7 dòng để làm cho một bảng ngày ảo. NB, tôi đã có thêm một 'khoản ON' đến tham gia để có được nó để làm việc: ) inc1 ON days.open_day = incidents.open_day GROUP BY days.open_day BTW, NZ là nơi hoang dã mọi thứ là gì? – Nathan

+0

oops cảm ơn, cố định. Có, chúng tôi có luẩn quẩn .. tuataras .. và tuyệt vời lớn .. kiwis .. vâng. – Blorgbeard

+0

Bạn là anh hùng của tôi. – Nathan

0

Bạn có thể tạo biến bảng với các ngày bạn cần và sau đó RIGHT JOIN vào nó không? Ví dụ,

DECLARE @dateTable TABLE ([date] SMALLDATETIME) 

INSERT INTO @dateTable 
VALUES('26 FEB 2009') 
INSERT INTO @dateTable 
VALUES('27 FEB 2009') 
-- etc 

SELECT 
    COUNT(*) AS "Calls", 
    MAX(open_time), 
    open_day 
FROM 
    (
SELECT 
incident_id, 
opened_by, 
open_time - (9.0/24) AS open_time, 
DATEPART(dd, (open_time-(9.0/24))) AS open_day 
    FROM incidentsm1 
    RIGHT JOIN @dateTable dates 
    ON incidentsm1.open_day = dates.date 
    WHERE 
DATEDIFF(DAY, open_time-(9.0/24), GETDATE())< 7 

) inc1 
GROUP BY open_day 

Tình hình lý tưởng hơn tuy nhiên, sẽ có một đối tượng bảng với số ngày trong

+0

Tôi chỉ có thể sử dụng một câu lệnh SQL, vì vậy có vẻ như tôi có thể thêm vào 'DECLARE' nhưng tôi không thể chèn dữ liệu vào câu lệnh SELECT của mình. – Nathan

0

tôi sẽ đề nghị việc sử dụng một date table. Với bảng ngày tháng đã có sẵn, bạn có thể thực hiện RIGHT OUTER JOIN với bảng ngày để mang lại những ngày còn thiếu của bạn.

+0

xin lỗi, tôi chỉ có quyền truy cập chỉ đọc. Tôi có thể nghỉ mát để tham gia vào một cột ngày tôi khá chắc chắn sẽ luôn luôn có một giá trị cho mỗi ngày, nhưng nó có vẻ như có nên có một cách tốt hơn. – Nathan

0

Bạn có thể tạo tập hợp các ngày như là một phần của truy vấn của mình không? Một cái gì đó dọc theo dòng:

SELECT COUNT(*) AS Calls, ... 
    FROM incidentsm1 RIGHT OUTER JOIN 
     (SELECT date_values 
      FROM TABLE(('27 Feb 2009'), ('28 Feb 2009'), ('1 Mar 2009'), 
         ('2 Mar 2009'), ('3 Mar 2009'), ('4 Mar 2009'), 
         ('5 Mar 2009')) AS date_list 
     ) 
     ON ... 

Điều này được lấy cảm hứng từ một loại lai của các ký hiệu Informix và DB2 và được đảm bảo khá nhiều cú pháp không chính xác trong cả hai. Về cơ bản, có một cách trong DBMS của bạn tạo ra một bảng chữ trên bay. Một khả năng - xấu xí nhưng hầu như không thể làm được - sẽ là làm một UNION 7 chiều của các chữ được chọn từ 'kép' hoặc một số biểu thức bảng đảm bảo một hàng (theo điều kiện Informix, SELECT MDY(2,28,2009) FROM "informix".systables WHERE tabid = 1 UNION ...).

+0

Không có DUAL trong MSSQL, mặc dù tôi vẫn có thể có may mắn bằng cách sử dụng 'WITH' (http://technet.microsoft.com/en-us/library/ms175972(SQL.90).aspx) ... Ngoài ra, tôi cần truy vấn này để chạy thường xuyên, vì vậy tôi không thể mã hóa các ngày nhưng phải tính toán chúng bằng cách nào đó, có lẽ như 'DATEADD (DAY, -1, GETDATE())' – Nathan

+0

Đủ công bằng; trong Informix, đó sẽ là TODAY - 1, v.v ... –

+0

Lưu ý, không cần DUAL trong mssql, vì bạn không cần mệnh đề từ - theo như sự hiểu biết của tôi về DUAL đi :) – Blorgbeard

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