【问题标题】:Contiguous Dates连续日期
【发布时间】:2015-12-03 17:06:10
【问题描述】:

这是我正在使用的表格:

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 字段,这是它们的分组方式。

【问题讨论】:

  • 如果样本数据中没有 memberID 字段,我们无法知道您为什么选择以这种方式合并记录。
  • 添加了memberid,希望对您有帮助
  • 123 的开始/结束日期如何重叠?例如:2013/01/01-2013/12/31 & 2013/05/01 - 2013/12/31
  • 是的,我也不明白结果。当不同的重叠开始日期和结束日期没有间隔时,为什么会有 2 行?应该只有一行。
  • 很抱歉,我的错字很多..希望现在更有意义..感谢您指出这一点

标签: sql sql-server tsql


【解决方案1】:

我以前不得不处理这种事情 我用这样的东西

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

【讨论】:

  • 这太棒了,而且很容易理解。非常感谢您的帮助!
  • 对于我这种情况的未来人,在JOIN @Membership m ON MembershipStartDate&lt;= SignificantDate AND SignificantDate &lt;= MembershipEndDate 添加AND m.MemberID = sd.MemberID。此外,这很容易修改为在时间级别上工作,只需将日期更改为秒,将日期更改为日期时间。正如赫尔曼所说,这个答案太棒了,我这辈子都想不通。
猜你喜欢
  • 2021-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 2022-11-25
  • 2010-12-10
相关资源
最近更新 更多