时间序列数据上的岛屿和差距问题
Islands and gaps problem on time-series data
我有一个示例数据,我一直在尝试获取所需的数据,如下所示。我也能够实施某种岛屿和差距解决方案。这是我达到的最接近预期数据的版本。
DROP TABLE IF EXISTS #data
CREATE TABLE #data(
factor varchar(50),
val int,
[start_date] date, [end_date] date
)
Go
INSERT INTO #data VALUES
('a', 15, '2021-01-01', '2021-01-05'),
('a', 15, '2021-01-08', '2021-01-10'),
('a', 20, '2021-01-11', '2021-01-20'),
('a', 15, '2021-01-21', '2099-01-01'),
('b', 10, '2021-01-01', '2021-01-04'),
('b', 12, '2021-01-05', '2021-01-13'),
('b', 12, '2021-01-17', '2021-01-19'),
('b', 12, '2021-01-20', '2021-01-23'),
('b', 10, '2021-01-24', '2099-01-01');
WITH value_cte As (
SELECT * ,
RANK() OVER(PARTITION BY factor ORDER BY [start_date]) - RANK() OVER(PARTITION BY factor, val ORDER BY [start_date]) grp
FROM #data
)
SELECT factor, val, MIN(start_date) st, MAX(end_date) ed
FROM value_cte
GROUP BY factor, val, grp
ORDER BY factor, st
上述查询的结果:
预期结果:
factor val st ed
a 15 2021-01-01 2021-01-05
a 15 2021-01-08 2021-01-10
a 20 2021-01-11 2021-01-20
a 15 2021-01-21 2099-01-01
b 10 2021-01-01 2021-01-04
b 12 2021-01-05 2021-01-13
b 12 2021-01-17 2021-01-23
b 10 2021-01-24 2099-01-01
即使两个连续岛的值相同并且存在间隙,则不应合并该间隙,如果两个岛是连续的,则应将它们合并。不幸的是,我无法在此处更改源(示例数据结构)
您可以使用 lag()
来确定“孤岛”的起点——即没有重叠的地方。然后使用基于日期算术的累计和:
select factor, val, min(start_date), max(end_date)
from (select d.*,
sum(case when prev_end_date >= dateadd(day, -1, start_date) then 0 else 1 end) over (partition by factor, val order by start_date) as grp
from (select d.*,
lag(end_date) over (partition by factor, val order by start_date) as prev_end_date
from data d
) d
) d
group by factor, val, grp
order by factor, min(start_date);
Here 是 SQL Fiddle.
我有一个示例数据,我一直在尝试获取所需的数据,如下所示。我也能够实施某种岛屿和差距解决方案。这是我达到的最接近预期数据的版本。
DROP TABLE IF EXISTS #data
CREATE TABLE #data(
factor varchar(50),
val int,
[start_date] date, [end_date] date
)
Go
INSERT INTO #data VALUES
('a', 15, '2021-01-01', '2021-01-05'),
('a', 15, '2021-01-08', '2021-01-10'),
('a', 20, '2021-01-11', '2021-01-20'),
('a', 15, '2021-01-21', '2099-01-01'),
('b', 10, '2021-01-01', '2021-01-04'),
('b', 12, '2021-01-05', '2021-01-13'),
('b', 12, '2021-01-17', '2021-01-19'),
('b', 12, '2021-01-20', '2021-01-23'),
('b', 10, '2021-01-24', '2099-01-01');
WITH value_cte As (
SELECT * ,
RANK() OVER(PARTITION BY factor ORDER BY [start_date]) - RANK() OVER(PARTITION BY factor, val ORDER BY [start_date]) grp
FROM #data
)
SELECT factor, val, MIN(start_date) st, MAX(end_date) ed
FROM value_cte
GROUP BY factor, val, grp
ORDER BY factor, st
上述查询的结果:
预期结果:
factor val st ed
a 15 2021-01-01 2021-01-05
a 15 2021-01-08 2021-01-10
a 20 2021-01-11 2021-01-20
a 15 2021-01-21 2099-01-01
b 10 2021-01-01 2021-01-04
b 12 2021-01-05 2021-01-13
b 12 2021-01-17 2021-01-23
b 10 2021-01-24 2099-01-01
即使两个连续岛的值相同并且存在间隙,则不应合并该间隙,如果两个岛是连续的,则应将它们合并。不幸的是,我无法在此处更改源(示例数据结构)
您可以使用 lag()
来确定“孤岛”的起点——即没有重叠的地方。然后使用基于日期算术的累计和:
select factor, val, min(start_date), max(end_date)
from (select d.*,
sum(case when prev_end_date >= dateadd(day, -1, start_date) then 0 else 1 end) over (partition by factor, val order by start_date) as grp
from (select d.*,
lag(end_date) over (partition by factor, val order by start_date) as prev_end_date
from data d
) d
) d
group by factor, val, grp
order by factor, min(start_date);
Here 是 SQL Fiddle.