按连续日期分组,忽略 SQL 中的周末
Posted
技术标签:
【中文标题】按连续日期分组,忽略 SQL 中的周末【英文标题】:Grouping by contiguous dates, ignoring weekends in SQL 【发布时间】:2011-03-10 16:44:47 【问题描述】:我正在尝试对连续的日期范围进行分组,以显示每个范围的最小和最大日期。到目前为止,我使用了与此类似的解决方案:http://www.sqlservercentral.com/articles/T-SQL/71550/ 但是我使用的是 SQL 2000,所以我必须进行一些更改。到目前为止,这是我的程序:
create table #tmp
(
date smalldatetime,
rownum int identity
)
insert into #tmp
select distinct date from testDates order by date
select
min(date) as dateRangeStart,
max(date) as dateRangeEnd,
count(*) as dates,
dateadd(dd,-1*rownum, date) as GroupID
from #tmp
group by dateadd(dd,-1*rownum, date)
drop table #tmp
除了一个问题:周末,它完全按照我想要的方式工作。我的数据集没有周末日期的记录,这意味着找到的任何组最多为 5 天。例如,在下面的结果中,我希望最后 3 个组显示为一条记录,dateRangeStart 为 10/6,dateRangeEnd 为 10/20:
如果休息时间只是周末,我是否可以通过某种方式将其设置为忽略日期范围内的休息时间?
感谢您的帮助。
【问题讨论】:
为什么不创建一个带有周数列的永久日历表? @Martin 你能详细说明一下吗?我总是可以使用 datepart 获得周数,但我不明白这将如何帮助改变我的分组。 哦,对了,我看错了问题。 【参考方案1】:已编辑
我不太喜欢我之前的想法。我认为这是一个更好的:
-
根据要分组的一组日期中的第一个和最后一个日期,准备所有中间周末日期的列表。
将工作日期与周末日期一起插入,排序后,它们都将按照正常顺序分配
rownum
值。
使用您的方法查找连续范围并进行以下修改:
1) 计算dateRangeStart
时,如果是周末,则选择最近的下一个工作日;
2) 对应dateRangeEnd
,如果是周末日期,则选择最近的前一个工作日;
3) 在为小组计算日期时,只选择工作日。
从结果集中仅选择dates > 0
所在的行,从而消除仅由周末组成的组。
这是该方法的一个实现,假设一周从星期日开始(DATEPART
返回1
),周末是星期日和星期六:
DECLARE @tmp TABLE (date smalldatetime, rownum int IDENTITY);
DECLARE @weekends TABLE (date smalldatetime);
DECLARE @minDate smalldatetime, @maxDate smalldatetime, @date smalldatetime;
/* #1 */
SELECT @minDate = MIN(date), @maxDate = MAX(date)
FROM testDates;
SET @date = @minDate - DATEPART(dw, @minDate) + 7;
WHILE @date < @maxDate BEGIN
INSERT INTO @weekends
SELECT @date UNION ALL
SELECT @date + 1;
SET @date = @date + 7;
END;
/* #2 */
INSERT INTO @tmp
SELECT date FROM testDates
UNION
SELECT date FROM @weekends
ORDER BY date;
/* #3 & #4 */
SELECT *
FROM (
SELECT
MIN(date + CASE DATEPART(dw, date) WHEN 1 THEN 1 WHEN 7 THEN 2 ELSE 0 END)
AS dateRangeStart,
MAX(date - CASE DATEPART(dw, date) WHEN 1 THEN 2 WHEN 7 THEN 1 ELSE 0 END)
AS dateRangeEnd,
COUNT(CASE WHEN DATEPART(dw, date) NOT IN (1, 7) THEN date END) AS dates,
DATEADD(d, -rownum, date) AS GroupID
FROM @tmp
GROUP BY DATEADD(d, -rownum, date)
) s
WHERE dates > 0;
【讨论】:
谢谢!这很好用。我曾考虑插入周末日期来解决范围问题,但我认为这会比这更困难。以上是关于按连续日期分组,忽略 SQL 中的周末的主要内容,如果未能解决你的问题,请参考以下文章