考虑以下内容:
CREATE TABLE Members (MemberID INT)
INSERT Members VALUES (1001)
CREATE TABLE PCPs (PCPID INT)
INSERT PCPs VALUES (231)
INSERT PCPs VALUES (327)
INSERT PCPs VALUES (390)
CREATE TABLE Plans (PlanID INT)
INSERT Plans VALUES (555)
INSERT Plans VALUES (762)
CREATE TABLE MemberPCP (
MemberID INT
, PCP INT
, StartDate DATETIME
, EndDate DATETIME)
INSERT MemberPCP VALUES (1001, 231, '2002-01-01', '2002-06-30')
INSERT MemberPCP VALUES (1001, 327, '2002-07-01', '2003-05-31')
INSERT MemberPCP VALUES (1001, 390, '2003-06-01', '2003-12-31')
CREATE TABLE MemberPlans (
MemberID INT
, PlanID INT
, StartDate DATETIME
, EndDate DATETIME)
INSERT MemberPlans VALUES (1001, 555, '2002-01-01', '2003-03-31')
INSERT MemberPlans VALUES (1001, 762, '2003-04-01', '2003-12-31')
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种简洁的方法来构建成员/ PCP /计划关系的时间表,其中PCP或成员计划的更改将导致结果中的单独的开始/结束行.例如,如果超过几年,一名成员改变他们的PCP两次并且他们的计划一次,但每次在不同的日期,我会看到类似以下内容:
MemberID PCP PlanID StartDate EndDate
1001 231 555 2002-01-01 2002-06-30
1001 327 555 2002-07-01 2003-03-31
1001 327 762 2003-04-01 2003-05-31
1001 390 762 2003-06-01 2003-12-31
Run Code Online (Sandbox Code Playgroud)
如您所见,我需要为每个日期期间单独的结果行,这涉及成员/ PCP /计划关联的差异.我有一个解决方案,但它在WHERE子句中有很多CASE语句和条件逻辑.我只是想有一个更简单的方法来做到这一点.
谢谢.
我的方法是将每个成员的开始日期的独特组合作为起点,然后从那里构建查询的其他部分:
--
-- Traverse down a list of
-- unique Member ID and StartDates
--
-- For each row find the most
-- recent PCP for that member
-- which started on or before
-- the start date of the current
-- row in the traversal
--
-- For each row find the most
-- recent PlanID for that member
-- which started on or before
-- the start date of the current
-- row in the traversal
--
-- For each row find the earliest
-- end date for that member
-- (from a collection of unique
-- member end dates) that happened
-- after the start date of the
-- current row in the traversal
--
SELECT MemberID,
(SELECT TOP 1 PCP
FROM MemberPCP
WHERE MemberID = s.MemberID
AND StartDate <= s.StartDate
ORDER BY StartDate DESC
) AS PCP,
(SELECT TOP 1 PlanID
FROM MemberPlans
WHERE MemberID = s.MemberID
AND StartDate <= s.StartDate
ORDER BY StartDate DESC
) AS PlanID,
StartDate,
(SELECT TOP 1 EndDate
FROM (
SELECT MemberID, EndDate
FROM MemberPlans
UNION
SELECT MemberID, EndDate
FROM MemberPCP) e
WHERE EndDate >= s.StartDate
ORDER BY EndDate
) AS EndDate
FROM (
SELECT
MemberID,
StartDate
FROM MemberPlans
UNION
SELECT
MemberID,
Startdate
FROM MemberPCP
) s
ORDER BY StartDate
Run Code Online (Sandbox Code Playgroud)