计算日期之间的行数

时间:2010-02-12 13:33:46

标签: sql tsql count case where-clause

我正在使用CTE生成一系列日期。

12/02/2010 10:00:00 12/02/2010 10:59:59
12/02/2010 11:00:00 12/02/2010 11:59:59
12/02/2010 12:00:00 12/02/2010 12:59:59

然后我将其加入到包含大量日期的索引视图中。

我有两个日期范围计数选项

1)我会对SUM(case)测试log_date以测试它是否在开始和结束日期之间,+ 1表示true,0表示false - 所以如果没有结果我将总是得到'0'

12/02/2010 10:00:00 12/02/2010 10:59:59    0
12/02/2010 11:00:00 12/02/2010 11:59:59    1
12/02/2010 12:00:00 12/02/2010 12:59:59    0

2)我可以使用每个日期范围的WHERE子句计算(*)。

12/02/2010 11:00:00 12/02/2010 11:59:59    1

正如您所期望的那样1)是有效的但是在性能上有很大的开销2)可能会有8000%的效率但如果应用了一个在指定日期范围之间返回null结果的过滤器,则无法返回范围。

有没有办法使用efficent WHERE子句但保留日期范围行详细说明'0'?

这里是案例解决方案的一些SQL:

SELECT     [LABEL], [Display Start Date], [Display End Date], 
    SUM(CASE WHEN ([LOG].line_date BETWEEN [Start Date] AND [End Date]) THEN 1 ELSE 0 END) AS [Total Calls], 
    SUM(CASE WHEN ([LOG].line_date BETWEEN [Start Date] AND [End Date]) AND ([LOG].line_result = 1) THEN 1 ELSE 0 END) AS [1 Calls], 

FROM         [DATE RANGE FUNCTION] LEFT JOIN
                      dbo.vCallLog WITH (noexpand) as [LOG] on 0 > -1
GROUP BY [Start Date], [End Date], [Display Start Date], [Display End Date], [LABEL]

这是WHERE解决方案的一些SQL:

SELECT     [LABEL], [Display Start Date], [Display End Date], 
                    COUNT(dbo.vCallLog.line_id) AS [Total Calls], 
                    SUM(CASE WHEN ([LOG].line_result = 1) THEN 1 ELSE 0 END) AS [1 Calls], 
FROM         [DATE RANGE FUNCTION] LEFT JOIN
                      dbo.vCallLog WITH (noexpand) as [LOG] on 0> -1
WHERE     ([LOG].line_date BETWEEN [Start Date] AND [End Date]) 
GROUP BY [Start Date], [End Date], [Display Start Date], [Display End Date], [LABEL]

3 个答案:

答案 0 :(得分:2)

好的,一点点pokery,我意识到我为自己做了一个小问题:

问题是WHERE子句及其对COUNT子句的位置。如果我正在使用WHERE&依靠相同的结果集,然后在日期之间我没有得到任何零行。但是,我计算所有内容并从同一结果集中省略WHERE并将WHERE子句放在JOIN 即[x]左连接中(从[b]中选择[a],其中[a]位于@x和amp之间; @y)作为[c] 我返回所有行,计数然后逐字计数。

我认为问题是WHERE子句先前省略了count选择,因为没有采取任何行动(根据编译器)

答案 1 :(得分:1)

如果我理解你,你可以试试

DECLARE @DateRanges TABLE(
        StartDate DATETIME,
        EndDate DATETIME
)

INSERT INTO @DateRanges (StartDate,EndDate) SELECT '12/02/2010 10:00:00','12/02/2010 10:59:59' 
INSERT INTO @DateRanges (StartDate,EndDate) SELECT '12/02/2010 11:00:00','12/02/2010 11:59:59' 
INSERT INTO @DateRanges (StartDate,EndDate) SELECT '12/02/2010 12:00:00','12/02/2010 12:59:59'

DECLARE @DateValues TABLE(
        DateVal DATETIME
)

INSERT INTO @DateValues (DateVal) SELECT '12/02/2010 11:00:00'
INSERT INTO @DateValues (DateVal) SELECT '12/02/2010 11:01:00'
INSERT INTO @DateValues (DateVal) SELECT '12/02/2010 12:01:00'

SELECT  t.StartDate,
        t.EndDate,
        COUNT(tv.DateVal) CountVal
FROM    @DateRanges t LEFT JOIN
        @DateValues tv ON tv.DateVal BETWEEN t.StartDate AND t.EndDate
GROUP BY    t.StartDate,
            t.EndDate

输出

StartDate               EndDate                 CountVal
----------------------- ----------------------- -----------
2010-12-02 10:00:00.000 2010-12-02 10:59:59.000 0
2010-12-02 11:00:00.000 2010-12-02 11:59:59.000 2
2010-12-02 12:00:00.000 2010-12-02 12:59:59.000 1

答案 2 :(得分:0)

啊,臭名昭着的地方。当你有LEFT JOIN和WHERE子句来测试右栏中的条件时,你必须包括

WHERE (<Condition based on rightHandTable.Column> OR rightHandTable.Column IS NULL)

当你有条件的化合物时,将尾随OR语句放在parens中也是个好主意:

WHERE a=1 AND b=1 OR b iS NULL

当a和b = 1或b为空时

,此结果为真

不同
WHERE a=1 AND (b=1 OR b is NULL)

这意味着必须为1且b必须为1或null