开发者

Grouping by contiguous dates, ignoring weekends in SQL

I'm attempting to group contiguous date ranges to show the minimum and maximum date for each range. So far I've used a solution similar to this one: http://www.sqlservercentral.com/articles/T-SQL/71550/ however I'm on SQL 2000 so I had to make some changes. This is my procedure so far:

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

It works exactly how I want except for one issue: weekends. My data sets have no records for weekend dates, which means any group found is at most 5 days. For instance, in the results below, I would like the last 3 groups to show up as a single record, with a dateRangeStart of 10/6 and a d开发者_如何学PythonateRangeEnd of 10/20:

Grouping by contiguous dates, ignoring weekends in SQL

Is there some way I can set this up to ignore a break in the date range if that break is just a weekend?

Thanks for the help.


EDITED

I didn't like my previous idea very much. Here's a better one, I think:

  1. Based on the first and the last dates from the set of those to be grouped, prepare the list of all the intermediate weekend dates.
  2. Insert the working dates together with weekend dates, ordered, so they would all be assigned rownum values according to their normal order.
  3. Use your method of finding contiguous ranges with the following modifications:

    1) when calculating dateRangeStart, if it's a weekend date, pick the nearest following weekday;

    2) accordingly for dateRangeEnd, if it's a weekend date, pick the nearest preceding weekday;

    3) when counting dates for the group, pick only weekdays.

  4. Select from the resulting set only those rows where dates > 0, thus eliminating the groups formed only of the weekends.

And here's an implementation of the method, where it is assumed, that a week starts on Sunday (DATEPART returns 1) and weekend days are Sunday and Saturday:

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;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜