SQL Count的值为零

时间:2015-12-10 13:09:41

标签: sql sql-server count

我想在过去24小时内为我的数据集创建一个图表。

我找到了一个有效的解决方案,但这非常糟糕,因为我在外面加入数据库中的每一行,因为我使用的是(现已弃用)"所有"组中的参数。

这是目前有效的解决方案。 首先,我宣布从现在起24小时后的日期间隔。我宣布它两次,所以我可以在以后的程序中使用它。

Declare @StartDate datetime = dateadd(hour, -24, getdate())
Declare @StartDateProc datetime = dateadd(hour, -24, getdate())
Declare @EndDate datetime = getdate()

我将日期填充到临时表中,包括一个特殊的格式化日期。

create table #tempTable
(
    Date datetime,
    DateString varchar(11)
)

while @StartDate <= @EndDate
begin
    insert into #tempTable (Date, DateString)  
    values (@StartDate, convert(varchar(8), @StartDate, 5) + '-' + convert(varchar(2), @StartDate, 108));

    SET @StartDate = dateadd(hour,1, @StartDate);
end

这给了我这样的数据:

Date                              DateString
---------------------------------------------
2015-12-09 13:59:01.970           09-12-15-13
2015-12-09 14:59:01.970           09-12-15-14
2015-12-09 15:59:01.970           09-12-15-15
2015-12-09 16:59:01.970           09-12-15-16

所以我想要的是在匹配日期字符串上加入我的数据集并显示日期,即使匹配的行为零。

以下是查询的其余部分

select
    Date = c.Date,
    Amount = sum(c.Amount)
from 
    DbTable a
outer apply 
    (select 
         Date = b.DateString,
         Amount = count(*)
     from 
         #tempTable b
     where
         convert(varchar(8), a.DateColumn, 5) + '-' + convert(varchar(2), a.DateColumn, 108) = b.DateString
     group by all
         b.DateString) c
where 
    a.SomeParameter = 'test' and
    a.DateColumn >= @StartDateProc and
    a.DateColumn <= @EndDate
group by
    c.Date

drop table #tempTable

测试以显示实际数据:

Declare @StartDate datetime = dateadd(hour, -24, getdate())
Declare @EndDate datetime = getdate()

select  
    dateString = convert(varchar(8),a.DateColumn,5) + '-' + convert(varchar(2),a.DateColumn, 108),
    Amount = COUNT(*)
from 
    DbTable a   

where
    a.someParameter = 'test' and
    a.DateColumn>= dateadd(hour, -24, getdate()) and
    a.DateColumn<= getdate()

group by 
    convert(varchar(8),a.DateColumn,5) + '-' + convert(varchar(2),a.DateColumn, 108)

第一行输出:

dateString     Amount
09-12-15-14    1
09-12-15-15    1
09-12-15-16    1
09-12-15-17    3
09-12-15-18    1
09-12-15-22    3
09-12-15-23    2

正如您在此处所见,从19.00到21.00的时间没有数据。这就是我想要显示数据的方式:

dateString     Amount
09-12-15-14    1
09-12-15-15    1
09-12-15-16    1
09-12-15-17    3
09-12-15-18    1
09-12-15-19    0
09-12-15-20    0
09-12-15-21    0
09-12-15-22    3
09-12-15-23    2

2 个答案:

答案 0 :(得分:3)

通常情况下,这将使用left join而不是outer apply。逻辑很简单:保留第一个表中的所有行以及第二个表中的任何匹配信息。这意味着将日期表放在第一位:

select tt.DateString, count(t.DateColumn) as Amount
from #tempTable tt left join
     DbTable t
     on convert(varchar(8), t.DateColumn, 5) + '-' + convert(varchar(2), t.DateColumn, 108) = tt.DateString and 
        t.SomeParameter = 'test'
where tt.Date >= @StartDateProc and
      tt.Date <= @EndDate
group by tt.DateString;

此外,您对日期的比较似乎过于复杂,但如果它对您有效,则可行。

答案 1 :(得分:0)

这里最好的选择是使用DATETIME类型本身而不是失去使用索引的机会:

Declare @d datetime = GETDATE()

;WITH cte1 AS(SELECT TOP 25 -1 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) h 
              FROM master..spt_values),
      cte2 AS(SELECT DATEADD(hh, -h, @d) AS startdate, 
                     DATEADD(hh, -h + 1, @d) AS enddate 
              FROM cte1)
SELECT c.startdate, c.enddate, count(*) as amount
FROM cte2 c
LEFT JOIN DbTable a ON a.DateColumn >= c.startdate AND 
                       a.DateColumn < c.enddate AND
                       a.SomeParameter = 'test'
GROUP BY c.startdate, c.enddate