计算日期之间的行数
我正在使用 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
然后,我将其连接到包含大量日期的索引视图。
我有 2 个选项用于在日期范围之间进行计数
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%,但如果应用的过滤器在指定日期范围内返回空结果,则无法返回范围。
有没有办法使用有效的 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]
I'm using a CTE to generate a range of dates.
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
I then left join this to a indexed view containing huge amounts of date.
I have 2 options for counting between the date ranges
1) i would SUM(case) test the log_date to test if it is between the start and end dates, + 1 for true, 0 for false - so if no results i would always get '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) i can count(*) using a WHERE clause per date range.
12/02/2010 11:00:00 12/02/2010 11:59:59 1
As you would expect 1) is effective but has a massive overhead on performance 2) is possibly 8000% more efficent BUT fails to return the range should a filter be applied which returns null results between the specified date range.
Is there a way to use the efficent WHERE clause but retain the date range row detailing '0'?
here is some SQL for the case solution:
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]
here is some SQL for the WHERE solution:
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]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,有点狡猾,我意识到我给自己制造了一个小问题:
问题是 WHERE 子句及其相对于 COUNT 子句的位置。如果我使用 WHERE &依靠相同的结果集,那么日期之间的零行我什么也得不到。但是,如果我对所有内容进行计数并省略同一结果集中的 WHERE,并将 WHERE 子句放在 JOIN 中,即 [x] 左连接(从 [b] 中选择 [a],其中 @x & 之间的 [a] ; @y) as [c] 我返回所有行,然后按字面意思计数。
我认为问题是 WHERE 子句先前省略了计数选择,因为没有采取任何操作(根据编译器)
Ok, a little pokery and i realised i made a slight issue for my self:
The issue is the WHERE clause and its position to the COUNT clause. If i'm using WHERE & count on the same result set then i get nothing for zero rows between dates. IF, however, i count everything and omit the WHERE from the same result set and place the WHERE clause in the JOIN i.e [x] left join (select [a] from [b] where [a] between @x & @y) as [c] i return all the rows, count then litrally counts.
I think the issue was the WHERE clause previous ommited the count select because there was no action to take (according to the compiler)
如果我理解正确的话,你可以尝试类似
输出的东西
If I understand you correctly you could try something like
Output
啊,臭名昭著的 WHERE 陷阱。当您有一个 LEFT JOIN 和一个测试右侧列中的条件的 WHERE 子句时,您必须包括
当您有复合 where 条件时,将尾随 OR 语句放在括号中也是一个好主意:
当 a and 时,此计算结果为 true b = 1 或当 b 为 null
且与此不同时,
意味着 a 必须为 1 并且 b 必须为 1 或 null
Ah, infamous WHERE gotchas. When you have a LEFT JOIN and a WHERE clause that tests a condition in the righthand column, you DO have to include
It's also a good idea to put trailing OR statements in parens when you have compound where conditions:
this evaluates as true when a and b = 1 or when b is null
and is different from
this means a must be 1 and b must be 1 or null