按连续日期分组,忽略SQL中的周末

时间:2011-03-10 16:44:47

标签: sql sql-server-2000 sql-date-functions

我正在尝试对连续的日期范围进行分组,以显示每个范围的最小和最大日期。到目前为止,我已经使用了类似于这个的解决方案: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:

screenshot of results

我是否有某种方法可以将此设置为忽略日期范围内的休息时间,如果该休息只是一个周末?

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

<强> EDITED

我不太喜欢我以前的想法。我认为这是一个更好的一个:

  1. 根据要分组的一组中的第一个和最后一个日期,准备所有中间周末日期的列表。
  2. 将工作日期与订购的周末日期一起插入,以便根据正常顺序为所有人分配rownum个值。
  3. 使用您的方法查找连续范围,并进行以下修改:

    1)在计算dateRangeStart时,如果是周末日期,则选择最接近的工作日;

    2)相应地dateRangeEnd,如果是周末日期,则选择最近的工作日;

    3)在计算小组的日期时,只选择工作日。

  4. 从结果集中选择仅dates > 0的行,从而消除仅由周末组成的组。

  5. 这是该方法的一个实现,假设一周从星期日开始(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;