给出以下数据集:
| 开始日期|停止_日期|集团|
| - ------|- ------|- ------|
| 2010年2月14日|二○一○年十月二十日|1个|
| 二○一○年十月二十一日|二○一○年十一月十一日|1个|
| 2013年1月1日|2013年4月4日|第二章|
| 2013年2月2日|2011年5月5日|第二章|
我想合并属于同一组的日期,并基于:如果stop_dt + 1天=另一个元素的start_dt,或者如果start_dt在另一个元素的start_dt和stop_dt之间。
预期结果:
| 开始日期|停止_日期|
| - ------|- ------|
| 2010年2月14日|二○一○年十一月十一日|
| 2011年1月1日|2011年5月5日|
我可以通过处理整个数据集来实现这一点,但是,我想使用游标逐个元素地处理。用我目前的方法,我可以合并它们,但是我最终得到了其他不需要的记录(因为我正在进行双插入,而不是删除)
create procedure test_curser()
begin
DECLARE done BOOLEAN DEFAULT 0;
DECLARE p_id BIGINT UNSIGNED;
declare c1 cursor for
select id from initial_table;
DECLARE CONTINUE handler FOR SQLSTATE '02000'
SET done = 1;
open c1;
fetch c1 into p_id;
while not done do call sort(p_id);
fetch c1 into p_id;
end while;
close c1;
create procedure sort(in p_id int)
begin
insert into result(id, start_dt, stop_dt, grp)
(select id,start_dt, stop_dt, grp from initial_table where id = p_id);
# We check: If the table contain only one element then no merging is require, otherwise merge
if (select count(id) from result) > 1 then
insert into result(start_dt, stop_dt,grp)
(select if(r2.start_dt < r1.start_dt, r2.start_dt, r2.start_dt) as start_dt,
if(r2.stop_dt > r1.stop_dt, r2.stop_dt, r1.stop_dt) as stop_dt,
r1.grp
from result as r1 join result as r2
on r2.grp = r1.grp and
datediff(r2.stop_dt, r1.start_dt) = -1 or
(r1.start_dt between r2.start_dt and r2.stop_dt)
where r1.id = p_id);
else
select 'process...';
end if;
end
检查Demo
我使用的是10.4.12-MariaDB
谢谢。
1条答案
按热度按时间oymdgrw71#
光标非常麻烦,并且增加了解决该任务的复杂性。解决该任务的更简化的方式包括:
CASE
+运行总和为每个连续(stop_dt,start_dt)值(相差一天)生成岛MIN
和MAX
聚合函数对“grp”字段和按标识的岛新建的分区应用聚合然后,您可以使用以下命令创建“result”表:
检查here演示。
可选注解:为了更好地理解,我建议检查此查询的每一步的输出:
SELECT * FROM cte
SELECT * FROM cte2