【发布时间】:2020-03-03 03:39:33
【问题描述】:
我有以下数据集,其中人员具有 id 并且他们的数量会随着时间而变化,因此变化被记录为日期范围。有时在没有可用信息的日期范围内会出现空白。没事。但是,我想合并连续的日期范围,它们恰好具有相同的数量,而它跨越多个记录,例如 ID = 1 的第 2 行和第 3 行。
DECLARE @DataTable TABLE (
ID [int] NULL,
StartDate [date] NULL,
EndDate [date] NULL,
Amount [decimal](12,2) NULL
)
INSERT INTO @DataTable
SELECT 1, '20180101','20180513', 10.00 UNION ALL
SELECT 1, '20180630','20190301', 15.00 UNION ALL
SELECT 1, '20190302','20190615', 15.00 UNION ALL
SELECT 1, '20190616','20991231', 5.00 UNION ALL
SELECT 2, '20190101','20190331', 35.00 UNION ALL
SELECT 2, '20190401','20191031', 30.00 UNION ALL
SELECT 3, '20180505','20180930', 19.00 UNION ALL
SELECT 3, '20181001','20190228', 1.00 UNION ALL
SELECT 3, '20190501','20190815', 1.00 UNION ALL
SELECT 3, '20190819','20190827', 5.00 UNION ALL
SELECT 3, '20190828','20991231', 1.00 UNION ALL
SELECT 4, '2017-10-01', '2017-12-31', 688.96 UNION ALL
SELECT 4, '2018-01-01', '2018-04-30', 707.96 UNION ALL
SELECT 4, '2018-05-01', '2018-05-31', 783.96 UNION ALL
SELECT 4, '2018-06-01', '2018-12-31', 707.96 UNION ALL
SELECT 4, '2019-01-01', '2019-03-31', 707.96 UNION ALL
SELECT 4, '2019-04-01', '2019-04-30', 571.46 UNION ALL
SELECT 4, '2019-05-01', '2019-06-30', 707.96 UNION ALL
SELECT 4, '2019-07-01', '2099-12-31', 707.96
;
我通过使用 dimDate 在开始日期和结束日期之间生成日期线来解决这个问题,然后记录金额与先前记录相比发生变化或 ID 存在日期差距的位置。然后我使用下一个可用的记录日期作为结束日期。查询如下:
WITH DateList AS (
SELECT DT.*, DD.DateOnly AS RecordDate
FROM @DataTable DT
INNER JOIN dimDate DD ON DT.StartDate <= DD.DateOnly AND CASE WHEN DT.EndDate > GETDATE() THEN CONVERT(DATE,GETDATE()) ELSE DT.EndDate END >= DD.DateOnly
)
, PrevValue AS (
SELECT
*
, LAG(RecordDate) OVER (PARTITION BY ID ORDER BY RecordDate) AS PrevDate
, LAG(Amount) OVER (PARTITION BY ID ORDER BY RecordDate) AS PrevAmt
FROM DateList
)
, KeepHistory AS (
SELECT
*
FROM PrevValue
WHERE Amount <> PrevAmt OR PrevAmt IS NULL OR DATEADD(DAY,1,PrevDate) <> RecordDate OR PrevDate IS NULL
)
, FINAL AS (
SELECT
*
, LEAD(PrevDate) OVER (PARTITION BY ID ORDER BY StartDate) AS NextEndDate
FROM KeepHistory
)
SELECT
ID
, StartDate
, CASE WHEN NextEndDate > EndDate THEN NextEndDate ELSE EndDate END AS EndDate
, Amount
FROM FINAL
我的问题是有另一种方法可以解决此问题,而无需通过 dimDate 或在开始日期和结束日期之间生成日期。我可以通过使用诸如here之类的间隙和孤岛问题之类的窗口函数来实现这一点吗?
如果您发现我当前的解决方案有任何问题,请告诉我。 谢谢。
关于@Larnu 响应,您更新后的查询适用于大多数 .我添加了 ID = 4 示例,该示例在合并其第 4 行和第 5 行时似乎会导致问题。当第 6 行的数量不同时,它也会合并第 7 行。
ID = 4 4th, 5th and 7th are merged; 6th one has different amount
【问题讨论】:
标签: sql sql-server tsql