缺少零值;公司加入零值的日期

时间:2015-05-06 12:20:19

标签: sql sql-server

这是SQL Server数据库上的T-SQL。

我有一个查询应该创建一个尾随30天的日期。然后,我加入了在每个日期创建的门票数量,并将其分开。

这是我的问题:

SELECT 
   dt.dt,
   CASE 
      WHEN tcr.CreatedCount IS NULL 
        THEN 0 
        ELSE tcr.CreatedCount 
   END AS 'CreatedCount',
   CASE 
      WHEN tcl.ClosedCount IS NULL 
        THEN 0 
        ELSE tcl.ClosedCount 
   END AS 'ClosedCount',
   tcr.cname
FROM
   (SELECT 
       dt = cast(DATEADD(DAY, (- 1 * n), getdate()) AS date)
    FROM
       (SELECT TOP (30) 
           n = ROW_NUMBER() OVER (ORDER BY m1.number) - 1
        FROM 
           [master].dbo.spt_values AS m1
        CROSS JOIN 
           [master].dbo.spt_values AS m2) X
    ) dt
LEFT JOIN
    (SELECT 
        COUNT(a.TicketNbr) AS CreatedCount,
        CAST(a.date_entered AS date) AS 'DayCreated',
        a.company_name cname,
        a.company_recid cid
     FROM 
        v_rpt_Service a
     LEFT JOIN 
        Company ON a.company_name = Company.Company_Name
     WHERE 
        (a.Board_Name = 'SOC - Incident'
         OR a.Board_Name = 'SOC - Service' 
         OR a.Board_Name = 'SOC - Escalation')
     GROUP BY 
         CAST(a.date_entered AS date), a.company_name, a.company_recid) tcr ON dt.dt = tcr.DayCreated
LEFT JOIN
   (SELECT 
       COUNT(a.TicketNbr) AS ClosedCount,
       CAST(a.date_closed AS date) AS 'DayClosed',
       a.company_recid
    FROM 
       v_rpt_Service a
    LEFT JOIN 
       Company ON a.company_name = Company.Company_Name
    WHERE 
       (a.Board_Name = 'SOC - Incident' OR
        a.Board_Name = 'SOC - Service' OR
        a.Board_Name = 'SOC - Escalation')
    GROUP BY 
       CAST(a.date_closed AS date), a.company_recid) tcl ON dt.dt = tcl.DayClosed AND tcl.company_recid = tcr.cid
ORDER BY 
    cname, dt

这个想法是数据显示每个公司的一个月的日期,其中包含按日期创建和关闭的计数。目前,它显示closed票证的0个计数,但不显示created。任何没有创建票证的日期都将被完全省略。

以下是几乎的示例数据,我需要它:

Query Sample Data

如何让此查询显示所有行,而不是省略那些创建了0的行?

编辑:我应该提到我不能使用WITH x AS或参数。此查询将进入拒绝这些内容的第三方报告应用程序。

2 个答案:

答案 0 :(得分:1)

问题是,在检查创建和关闭之前,您需要每个公司的完整列表(每天)。我打赌,如果你检查一下你的结果,你会发现你的三十天中每一天至少有一条记录。

首先尝试获取所有公司的列表,然后将其与所有日期的列表相结合,并从那里开始。我在下面捅了一下:

SELECT 
   dt.dt,
   CASE 
      WHEN tcr.CreatedCount IS NULL 
        THEN 0 
        ELSE tcr.CreatedCount 
   END AS 'CreatedCount',
   CASE 
      WHEN tcl.ClosedCount IS NULL 
        THEN 0 
        ELSE tcl.ClosedCount 
   END AS 'ClosedCount',
   c.cname
FROM
    (SELECT DISTINCT company_recid, company_name AS cname
    FROM v_rpt_service) c 
LEFT JOIN 
   (SELECT 
       dt = cast(DATEADD(DAY, (- 1 * n), getdate()) AS date)
    FROM
       (SELECT TOP (30) 
           n = ROW_NUMBER() OVER (ORDER BY m1.number) - 1
        FROM 
           [master].dbo.spt_values AS m1
        CROSS JOIN 
           [master].dbo.spt_values AS m2) X
    ) dt ON 
        1=1
LEFT JOIN
    (SELECT 
        COUNT(a.TicketNbr) AS CreatedCount,
        CAST(a.date_entered AS date) AS 'DayCreated',
        a.company_name cname,
        a.company_recid cid
     FROM 
        v_rpt_Service a
     LEFT JOIN 
        Company ON a.company_name = Company.Company_Name
     WHERE 
        (a.Board_Name = 'SOC - Incident'
         OR a.Board_Name = 'SOC - Service' 
         OR a.Board_Name = 'SOC - Escalation')
     GROUP BY 
         CAST(a.date_entered AS date), a.company_name, a.company_recid) tcr ON dt.dt = tcr.DayCreated AND c.Company_recID = tcr.cid 
LEFT JOIN
   (SELECT 
       COUNT(a.TicketNbr) AS ClosedCount,
       CAST(a.date_closed AS date) AS 'DayClosed',
       a.company_recid
    FROM 
       v_rpt_Service a
    LEFT JOIN 
       Company ON a.company_name = Company.Company_Name
    WHERE 
       (a.Board_Name = 'SOC - Incident' OR
        a.Board_Name = 'SOC - Service' OR
        a.Board_Name = 'SOC - Escalation')
    GROUP BY 
       CAST(a.date_closed AS date), a.company_recid) tcl ON dt.dt = tcl.DayClosed AND c.Company_recID = tcl.company_recid 
ORDER BY 
    cname, dt

答案 1 :(得分:-1)

看起来您正在使用master.dbo.spt_values作为获取日期列表的方式,因此只有该表中包含的日期包含在输出中,但我可能会弄错。

如果您希望包含所有日期,那么最好使用CTE生成所需日期。在下面的这个例子中,它交叉加入日期,以便每个日期与每个公司连接。然后它将两个计数连接到日期和公司,这应该确保返回所有公司的所有日期。

DECLARE @EndDate DATE = GETDATE()
DECLARE @StartDate DATE = DATEADD(d,-29,@EndDate)

;WITH DateRanges AS
(SELECT @StartDate AS DateValue
UNION ALL
SELECT DATEADD(DAY, 1, DateValue) AS DateValue
FROM DateRanges
WHERE DateValue < @EndDate)

SELECT 
    d.DateValue AS Date, 
    c.Company_Name,
    ISNULL(tcr.CreatedCount,0) AS CreatedCount, 
    ISNULL(tcl.ClosedCount,0) AS ClosedCount

FROM DateRanges d
CROSS JOIN Company c
LEFT JOIN (SELECT
                COUNT(a.TicketNbr) AS CreatedCount, 
                CAST(a.date_entered AS date) AS 'DayCreated', 
                a.company_name AS cname, 
                a.company_recid AS cid
            FROM v_rpt_Service a 
            LEFT JOIN Company c
                ON a.company_name = c.Company_Name
            WHERE a.Board_Name IN ('SOC - Incident','SOC - Service','SOC - Escalation')
            GROUP BY 
                CAST(a.date_entered AS date), 
                a.company_name, 
                a.company_recid) tcr 
    ON d.DateValue = tcr.DayCreated 
    AND c.company_recid = tcr.company_recid

LEFT JOIN (SELECT      
                COUNT(a.TicketNbr) AS ClosedCount, 
                CAST(a.date_closed AS date) AS 'DayClosed', 
                a.company_recid
            FROM v_rpt_Service a
            WHERE a.Board_Name IN ('SOC - Incident','SOC - Service','SOC - Escalation')
            GROUP BY CAST(a.date_closed AS date), a.company_recid) tcl 
    ON d.DateValue = tcl.DayClosed 
    AND tcl.company_recid = tcr.company_recid