以下是我正在使用的表格:
MemberID MembershipStartDate MembershipEndDate
=================================================================
123 2010-01-01 00:00:00.000 2012-12-31 00:00:00.000
123 2011-01-01 00:00:00.000 2012-12-31 00:00:00.000
123 2013-05-01 00:00:00.000 2013-12-31 00:00:00.000
123 2014-01-01 00:00:00.000 2014-12-31 00:00:00.000
123 2015-01-01 00:00:00.000 2015-03-31 00:00:00.000
我想要的是创建一行显示连续成员资格, 如果会员资格超过2天,则会有第二行,并有新的开始和结束日期..
所以我要找的输出就像:
MemberID MembershipStartDate MembershipEndDate
=================================================================
123 2010-01-01 00:00:00.000 2012-12-31 00:00:00.000
123 2013-05-01 00:00:00.000 2015-03-31 00:00:00.000
这些日期附有一个memberID字段,它们是如何分组的。
答案 0 :(得分:2)
我以前不得不处理这类事情 我使用这样的东西
USE tempdb
--Create test Data
DECLARE @Membership TABLE (MemberID int ,MembershipStartDate date,MembershipEndDate date)
INSERT @Membership
(MemberID,MembershipStartDate,MembershipEndDate)
VALUES (123,'2010-01-01','2012-12-31'),
(123,'2011-01-01','2012-12-31'),
(123,'2013-05-01','2013-12-31'),
(123,'2014-01-01','2014-12-31'),
(123,'2015-01-01','2015-03-31')
--Create a table to hold all the dates that might be turning points
DECLARE @SignificantDates Table(MemberID int, SignificantDate date, IsMember bit DEFAULT 0)
--Populate table with the start and end dates as well as the days just before and just after each period
INSERT @SignificantDates (MemberID ,SignificantDate)
SELECT MemberID, MembershipStartDate FROM @Membership
UNION
SELECT MemberID,DATEADD(day,-1,MembershipStartDate ) FROM @Membership
UNION
SELECT MemberID,MembershipEndDate FROM @Membership
UNION
SELECT MemberID,DATEADD(day,1,MembershipEndDate) FROM @Membership
--Set the is member flag for each date that is covered by a membership
UPDATE sd SET IsMember = 1
FROM @SignificantDates sd
JOIN @Membership m ON MembershipStartDate<= SignificantDate AND SignificantDate <= MembershipEndDate
--To demonstrate what we're about to do, Select all the dates and show the IsMember Flag and the previous value
SELECT sd.MemberID, sd.SignificantDate,sd.IsMember, prv.prevIsMember
FROM
@SignificantDates sd
JOIN (SELECT
MemberId,
SignificantDate,
IsMember,
Lag(IsMember,1) OVER (PARTITION BY MemberId ORDER BY SignificantDate desc) AS prevIsMember FROM @SignificantDates
) as prv
ON sd.MemberID = prv.MemberID
AND sd.SignificantDate = prv.SignificantDate
ORDER BY sd.MemberID, sd.SignificantDate
--Delete the ones where the flag is the same as the previous value
delete sd
FROM
@SignificantDates sd
JOIN (SELECT MemberId, SignificantDate,IsMember, Lag(IsMember,1) OVER (PARTITION BY MemberId ORDER BY SignificantDate) AS prevIsMember FROM @SignificantDates ) as prv
ON sd.MemberID = prv.MemberID
AND sd.SignificantDate = prv.SignificantDate
AND prv.IsMember = prv.prevIsMember
--SELECT the Start date for each period of membership and the day before the following period of non membership
SELECT
nxt.MemberId,
nxt.SignificantDate AS MembershipStartDate,
DATEADD(day,-1,nxt.NextSignificantDate) AS MembershipEndDate
FROM
(
SELECT
MemberID,
SignificantDate,
LEAd(SignificantDate,1) OVER (PARTITION BY MemberId ORDER BY SignificantDate) AS NextSignificantDate,
IsMember
FROM @SignificantDates
) nxt
WHERE nxt.IsMember = 1