gpt4 book ai didi

SQL:从两个历史表构建时间线的最佳方式

转载 作者:行者123 更新时间:2023-12-04 12:42:32 25 4
gpt4 key购买 nike

考虑到以下情况:

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')

我正在寻找一种简洁的方法来构建成员/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

如您所见,对于涉及成员(member)/PCP/计划关联差异的每个日期期间,我需要一个单独的结果行。我有一个解决方案,但它在 WHERE 子句中有很多 CASE 语句和条件逻辑非常复杂。我只是想有一个更简单的方法来做到这一点。

谢谢。

最佳答案

与 T-SQL 兼容。我同意 Glenn 的一般方法。

另一个建议:如果您允许在您的业务期间之间跳跃,则此代码将需要进一步调整。否则,我认为从下一条记录的 StartDate 推迟 EndDate 值会更好地从您的代码中获得更多受控行为。在这种情况下,您希望在数据到达此查询之前确保规则。

编辑:刚刚从 Andriy M 的帖子中了解了 With 语句和 SQL Fiddle。您可以 see my answer at SQL Fiddle也。

编辑:修复了 Andriy 指出的错误。

WITH StartDates AS (
SELECT MemberId, StartDate FROM MemberPCP UNION
SELECT MemberId, StartDate FROM MemberPlans UNION
SELECT MemberId, EndDate + 1 FROM MemberPCP UNION
SELECT MemberId, EndDate + 1 FROM MemberPlans
),
EndDates AS (
SELECT MemberId, EndDate = StartDate - 1 FROM MemberPCP UNION
SELECT MemberId, StartDate - 1 FROM MemberPlans UNION
SELECT MemberId, EndDate FROM MemberPCP UNION
SELECT MemberId, EndDate FROM MemberPlans
),
Periods AS (
SELECT s.MemberId, s.StartDate, EndDate = min(e.EndDate)
FROM StartDates s
INNER JOIN EndDates e
ON s.StartDate <= e.EndDate
AND s.MemberId = e.MemberId
GROUP BY s.MemberId, s.StartDate
)
SELECT MemberId = p.MemberId,
pcp.PCP, pl.PlanId,
p.StartDate, p.EndDate
FROM Periods p
LEFT JOIN MemberPCP pcp
-- because of the way we divided period,
-- there will be one and only one record that fits this join clause
ON p.StartDate >= pcp.StartDate
AND p.EndDate <= pcp.EndDate
AND p.MemberId = pcp.MemberId
LEFT JOIN MemberPlans pl
ON p.StartDate >= pl.StartDate
AND p.EndDate <= pl.EndDate
AND p.MemberId = pl.MemberId
ORDER BY p.MemberId, p.StartDate

关于SQL:从两个历史表构建时间线的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11040488/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com