SQL Server Determine total number of aggregate weeks excluding overlap periods

rm5edbpk  于 2023-06-21  发布在  其他
关注(0)|答案(1)|浏览(70)

I have query which returns thousands of rows, with a number and name, fromdate and today. I need to calculate the total number of aggregate weeks but exclude the overlapping date range. I have not been able to find a way.

As you can see, the 7th row of data is 2018-09-12 and next starting date is 2018-09-08. All of these rows is only for one number, but in other number columns, there are a lot more overlaps but example is the same. I have to exclude these overlaps. e.g. in another example, row one is the whole month of January, and row two is a week from 10 to 17th in it. so this is another example.

I tried to do a self join on the table but could not figure it out.

select *
from #RW r1, #RW r2
where r1.number = r2.number and r1.name = r2.name 
and r1.Fromdate < r2.Fromdate and r1.todate > r2.Fromdate 
and r1.number = '887'

**NOTE: If daycount = 0 , then that row should be ignored. it was generated based on another condition before I exported.

numbernamefromdatetodatedaycount
887DAVNULLNULL0
887DAV30/05/201805/06/20186
887DAV05/06/201819/06/201814
887DAV19/06/201818/07/201829
887DAV18/07/201815/08/201828
887DAV15/08/201812/09/201828
887DAV08/09/201817/10/20180
887DAV17/10/201807/11/20180
887DAV28/11/201809/01/201942
887DAV09/01/201905/02/201927
887DAV06/02/201929/05/2019112
887DAV24/07/201907/08/20190
887DAV09/08/201909/08/20190
887DAV10/08/201910/08/20190
887DAV18/09/201917/11/201960
887DAV09/12/201920/01/202042
887DAV20/01/202017/02/202028
887DAV30/03/202030/03/20200
887DAV03/11/202110/11/20217
887DAV11/11/202114/12/202133
887DAV15/12/202131/01/202247
887DAV01/02/202227/02/202226
887DAV28/02/202202/03/20222
887DAV03/03/202230/03/202227
887DAV31/03/202212/04/202212
887DAV13/04/202227/04/202214
887DAV28/04/202224/05/202226
887DAV25/05/202222/06/202228
887DAV23/06/202220/07/202227
887DAV21/07/202216/08/202226
887DAV17/08/202214/09/202228
887DAV15/09/202209/11/202255
887DAV10/11/202207/12/202227
887DAV08/12/202211/01/202334
887DAV12/01/202305/02/202324
887DAV06/02/202321/02/202315
887DAV22/02/202323/03/202329
887DAV24/03/202308/05/202345
887DAV09/05/202305/06/202327
887DAV05/06/202305/07/202330

Desired output: the desired result set would be to have a new result set (with consecutive date ranges) excluding the date overlaps. e.g. in above example, I want to remove the dates from 2018-09-08 until 2018-09-11 as these 4 days are already covered by the row above it. So naturally it should be all rows showing based on chronologica order, with merged fromdate/todate. as you can see, there are gaps between dates and I can't go with Min(fromdate) | Max(todate).

numbernamefromdatetodatedaycount
887DAV30/05/201829/05/2019364
887DAV24/07/201907/08/201914
887DAV09/08/201910/08/20191
887DAV18/09/201917/11/201960
887DAV09/12/201917/02/202070
887DAV30/03/202030/03/20200
887DAV03/11/202102/03/2022119
887DAV03/03/202230/03/202227
887DAV31/03/202205/07/2023461

Thanks in advance for your help,

xpcnnkqh

xpcnnkqh1#

Here's my solution with recursive CTE

;WITH cteGeneratedDates AS (
        SELECT
            number,
            [name],
            fromdate,
            todate
        FROM TableName
        WHERE fromdate IS NOT NULL 
            AND daycount > 0 -- comment this out if 0 daycount should be counted

        UNION ALL
        SELECT
            number,
            [name],
            fromdate = DATEADD(DAY, 1, fromdate),
            todate
        FROM cteGeneratedDates
        WHERE DATEADD(DAY, 1, fromdate) <= todate
),
cteGroupedConsecutiveDates AS (
    SELECT
        number,
        [name],
        fromdate,
        ROW_NUMBER() OVER (PARTITION BY number, [name] ORDER BY fromdate) todate
    FROM cteGeneratedDates
    GROUP BY number, [name], fromdate
)
SELECT 
    number,
    [name],
    MIN(fromdate) fromdate,
    MAX(fromdate) todate,
    DATEDIFF(DAY, MIN(fromdate), MAX(fromdate))
FROM cteGroupedConsecutiveDates
GROUP BY
    number,
    [name],
    DATEDIFF(DAY, fromdate, todate)
ORDER BY fromdate
OPTION (MAXRECURSION 2000)

Though there's difference with your expected output because of the following: why do these groups not grouped under 1 row?

  • 03/11/2021 - 02/03/2022
  • 03/03/2022 - 30/03/2022
  • 31/03/2022 - 05/07/2023

In my solution, above ranges would be in the same group.

Also, there are no dates between 07/11/2018 and 28/11/2018, don't you think this group needs to be broken down? 30/05/2018 - 29/05/2019

相关问题