Return 当 COUNT(*) 为 NULL 时 GROUP BY 中为 0

Return 0 in GROUP BY when COUNT(*) is NULL

这是我的原始查询:

SELECT
    CAST(IndexedDate as varchar),
    COUNT(*) AS Logins
FROM
    Table
WHERE
    EventType = 'Login'
AND IndexedDate > DATEADD(mm, -1, GETDATE())
GROUP BY
    IndexedDate
ORDER BY
    IndexedDate DESC

这会留下空白,例如:

2016-09-13    41
2016-09-12    31
2016-09-09    15
2016-09-08    36

基于 this question,我尝试了以下方法,仍然收到了差距,但最重要的是结果是错误的(数字高得多):

SELECT
    CAST(IndexedDate as varchar),
    SUM(Case When COUNT(*) Is Null Then 0 Else COUNT(*)  End) AS Logins
FROM
...

我怎样才能让我的结果看起来像这样?

2016-09-13    41
2016-09-12    31
2016-09-11    0
2016-09-10    0
2016-09-09    15
2016-09-08    36

我检查了其他几个问题,但它们都涉及连接或其他不在我的场景中的因素。


更新

根据评论,我尝试了 OUTER JOIN。这次迭代终于运行成功了,但是结果有点倒退...

SELECT
        CAST(a.IndexedDate as varchar) as dt,
        COUNT(*) AS Logins
FROM 
        (
        SELECT *
        FROM Table
        WHERE IndexedDate > DATEADD(mm, -1, GETDATE())
        AND EventType = 'Login'
        ) a
FULL OUTER JOIN (
        SELECT DISTINCT(IndexedDate)
        FROM Table
        WHERE IndexedDate > DATEADD(mm, -1, GETDATE())
        ) b
ON 
        a.IndexedDate = b.IndexedDate
GROUP BY
        b.IndexedDate
ORDER BY
        b.IndexedDate DESC

结果:

2016-09-13    41
2016-09-12    31
(null)    1
(null)    1
2016-09-09    15
2016-09-08    36

我确认合计 b 包括缺失的日期。

这有效(在 SQL 服务器中)

declare @mindt date = (select min(IndexedDate ) from p);
declare @dtrange int = DATEDIFF(day,@mindt,(select max(IndexedDate ) from p));

with MyCte AS
    (select   MyCounter = 0
     UNION ALL
     SELECT   MyCounter + 1
     FROM     MyCte
     where    MyCounter < @dtrange)
select coalesce(IndexedDate , dateadd(d, mycounter, @mindt)) IndexedDate
, count(IndexedDate)
from   MyCte 
left join p
  on dateadd(d,mycounter,@mindt) = p.IndexedDate 
group by coalesce(IndexedDate , dateadd(d, mycounter, @mindt))
option (maxrecursion 0);

我们基本上需要两个主要数字,开始日期和日期范围。

我们为日期范围内的天数构建了一个快速计数器。

然后我们 select 日期范围内的每个槽并分配一个日期和一个值,如果有 none 我们创建一个 DateAdd 的日期并分配 0 作为值.

Here is a functional 例子

所以我将聚合从编辑翻转到我的原始 post 现在它正在工作:

查询

SELECT
        CAST(a.IndexedDate as varchar) as dt,
        COUNT(EventType) AS Logins
FROM 
        (
        SELECT DISTINCT(IndexedDate)
        FROM Table
        WHERE IndexedDate > DATEADD(mm, -1, GETDATE())
        ) a
FULL OUTER JOIN (
        SELECT *
        FROM Table
        WHERE IndexedDate > DATEADD(mm, -1, GETDATE())
        AND EventType = 'Login'
        ) b
ON 
        a.IndexedDate = b.IndexedDate
GROUP BY
        a.IndexedDate
ORDER BY
        a.IndexedDate DESC

结果

2016-09-13    41
2016-09-12    31
2016-09-11    0
2016-09-10    0
2016-09-09    15
2016-09-08    36

请注意,我必须将 COUNT(*) 替换为 COUNT(EventType),这样它就不会计算结果为 1 的聚合日期。