我有一个表,该表包含文件名和每个文件的时间戳范围,例如:
filename mindatetime maxdatetime
monitor_4.dat 2019-04-28 09:00:00 AM 2019-04-29 11:00:00 AM
monitor_4.dat 2019-04-28 11:00:00 AM 2019-04-29 18:00:00 PM
monitor_4.dat 2019-04-28 09:30:00 AM 2019-04-29 23:00:00 PM
monitor_5.dat 2019-04-28 07:00:00 AM 2019-04-28 10:00:00 AM
monitor_5.dat 2019-04-28 02:00:00 PM 2019-04-28 06:00:00 PM
monitor_5.dat 2019-04-28 09:00:00 AM 2019-04-28 03:00:00 PM
monitor_7.dat 2019-04-21 03:06:26.0 AM 2019-05-21 03:06:10.0 AM
monitor_7.dat 2019-05-21 03:06:10.001 AM 2019-05-24 03:06:11.0 AM
monitor_7.dat 2019-06-05 03:06:18.001 AM 2019-06-06 03:06:11.0 AM
monitor_7.dat 2019-05-24 03:06:11.001 AM 2019-06-05 03:06:18.0 AM
monitor_7.dat 2019-05-12 07:00:10.001 AM 2019-05-13 10:00:10.000 AM
monitor_7.dat 2019-05-15 09:30:10.001 AM 2019-05-18 11:30:10.000 AM
我需要删除多余的时间戳范围,即那些属于给定时间戳范围的时间戳。 在这种情况下,对于文件“ monitor_5.dat”,我们需要将mindatetime设置为7AM,将maxdatetime设置为6PM,因为它们形成了涵盖其他条目的逻辑最小和最大时间戳范围。
所以我的输出结果应该像这样:
filename mindatetime maxdatetime
monitor_4.dat 2019-04-28 09:00:00 AM 2019-04-29 23:00:00 PM
monitor_5.dat 2019-04-28 07:00:00 AM 2019-04-28 06:00:00 PM
monitor_7.dat 2019-04-21 03:06:26.0 AM 2019-06-05 03:06:18.0 AM
monitor_7.dat 2019-05-12 07:00:10.001 AM 2019-05-13 10:00:10.000 AM
monitor_7.dat 2019-05-15 09:30:10.001 AM 2019-05-18 11:30:10.000 AM
这仅需要通过SQL来实现。任何的意见都将会有帮助。我已经研究过Postgres中提供的“ tsrange”功能,但这并不能完全帮助我。
答案 0 :(得分:1)
此答案仅适用于PostgreSQL。您是否故意标记了MySQL?
您必须将表与其自身连接起来,并删除其他条目中包含的条目:
DELETE FROM mytable AS a
USING mytable AS b
WHERE a.filename = b.filename
AND tsrange(a.mindatetime, a.maxdatetime) <@ tsrange(b.mindatetime, b.maxdatetime)
AND (a.ctid, a.xmin::text) <> (b.ctid, b.xmin::text);
最后一个条件阻止将行与自身进行比较。
答案 1 :(得分:1)
这是一种空白和岛屿问题。我建议找到“重叠”发生的位置,然后使用累积总和来识别组。累积max()
为此:
select filename, min(mindatetime) as mindatetime,
max(maxdatetime) as maxdatetime
from (select t.*,
sum(case when prev_maxdatetime >= mindatetime then 0 else 1 end) over
(partition by filename order by mindatetime) as grp
from (select t.*,
max(maxdatetime) over
(partition by filename
order by mindatetime
rows between unbounded preceding and 1 preceding
) as prev_maxdatetime
from t
) t
) t
group by filename, grp;
最里面的子查询确定不重叠时间范围的起始位置。然后,中间查询对这些“开始”进行累加总和,以将分组标识符分配给每个组。然后,外部查询将按该组(和文件名)进行聚合。
您可以运行内部查询并查看它们产生什么值。
Here是db <>小提琴。就我而言,根据您在此处提出的问题,此方法可以正常工作。如果您有一个时间滞后要考虑这些值相同/重叠,请提出一个 new 问题,并清楚地说明您的逻辑。
编辑:
如果每个文件名只需要一条记录,则只需使用聚合:
select filename, min(mindatetime) as mindatetime,
max(maxdatetime) as maxdatetime
from t
group by filename;
第一个版本合并了行之间没有空格的行。这只是最早和最新的日期/时间。