提问人:SkyWalker 提问时间:10/26/2023 最后编辑:SkyWalker 更新时间:10/27/2023 访问量:67
有没有办法删除/更新时间序列中的重复值?
Is there a way to delete / update duplicate values in a time sequence?
问:
我有一个看起来像的表(不要介意数据库供应商,因为我在 ANSI SQL 中需要它):
create table edge (
parent_id int not null,
child_id int not null,
value float not null,
start date not null,
end date not null
)
然后,我将获得以下 CSV 输入数据:
1,2,0,2023-01-01,2023-01-10
1,2,0,2023-01-11,2023-01-20
1,2,0,2023-01-21,NULL
1,3,0,2023-01-01,2023-01-10
1,3,0,2023-01-11,2023-01-20
1,3,1,2023-01-21,NULL
请注意,如果父值为 1,子值为 2,则相同的值 0 会在多个日期间隔内重复,因此可以折叠为:
1,2,0,2023-01-01,NULL
1,3,0,2023-01-01,2023-01-20
1,3,1,2023-01-21,NULL
值 in 表示在另行通知之前有效。NULL
end
理想情况下,对于表边缘(是的,图形边缘)将有一个查询,该查询将生成第二个摘录的输出。目标是首先删除多余的行,然后更新剩余的最后一行,以匹配第一个已删除的行。start
start
我能得到的最接近的是以下内容,在这里我找到了所有要删除的冗余行:
SELECT *
FROM edge
WHERE (parent, child, value, start) IN (SELECT parent, child, value, end+1
FROM edge)
ORDER BY parent, child, start
然后,我需要执行更新步骤以使时间序列保持一致。另外,是完全匹配的,它是一个浮点数,但这至少适用于 PostgreSQL。value
如果无法使用 ANSI,我将有兴趣了解 PostgreSQL 案例。
答:
2赞
Stefanov.sm
10/27/2023
#1
我首先建议一个查询,该查询根据上述业务规则选择所需的行,这些行可以使用(作为视图?)而不删除。我正在使用非ANSI PostgreSQL的子句。distinct on
select distinct on (parent_id, child_id, value)
parent_id, child_id, value,
first_value(start_date) over (partition by parent_id, child_id, value order by start_date),
end_date
from edge;
order by parent_id, child_id, value, start_date desc;
如果这是不可接受的,则将查询调整为 CTE,然后删除这些不在其中的行。
这是一个符合 SQL 标准的版本,不带 .distinct on
select parent_id, child_id, value, sd start_date, end_date
from
(
select
row_number() over (partition by parent_id, child_id, value order by start_date desc) rn,
parent_id, child_id, value,
first_value(start_date) over (partition by parent_id, child_id, value order by start_date) sd,
end_date
from edge
) t
where rn = 1;
SQL Fiddle 演示
评论
0赞
jarlh
11/28/2023
接近标准符合,是保留字,即需要分隔为 .en.wikipedia.org/wiki/List_of_SQL_reserved_wordsvalue
"value"
1赞
maraca
10/27/2023
#2
如果日期范围是连续的,我认为最简单(但有点脏)的方法如下:
重命名表并设置为将来的唯一日期。
end
null
将值放入新的边表中:
SELECT parent_id, child_id, value, MIN(start), MAX(end) FROM edge_old GROUP BY parent_id, child_id, value
设置为与您之前设置的唯一日期匹配的位置,并删除旧表。
end
null
评论
0赞
maraca
10/27/2023
尽管如果将值设置回以前的值,则范围将是错误的。这有点过于简单化了。但是,在新表中插入所需范围的想法很有帮助,因为编写 select 语句更容易,该语句可以准确地选择所需的内容,而不是更新和删除行。
评论