我试图找出一种方法来删除重叠时间的记录,但我无法找出保持所有但这些记录重叠的一个的简单和优雅的方法。这个问题与this one类似,但有一些差异。我们的表看起来像:PostgreSQL查询删除重叠时间记录,同时保留最早?
╔════╤═══════════════════════════════════════╤══════════════════════════════════════╤════════╤═════════╗
║ id │ start_time │ end_time │ bar │ baz ║
╠════╪═══════════════════════════════════════╪══════════════════════════════════════╪════════╪═════════╣
║ 0 │ Mon, 18 Dec 2017 16:08:33 UTC +00:00 │ Mon, 18 Dec 2017 17:08:33 UTC +00:00 │ "ham" │ "eggs" ║
╟────┼───────────────────────────────────────┼──────────────────────────────────────┼────────┼─────────╢
║ 1 │ Mon, 18 Dec 2017 16:08:32 UTC +00:00 │ Mon, 18 Dec 2017 17:08:32 UTC +00:00 │ "ham" │ "eggs" ║
╟────┼───────────────────────────────────────┼──────────────────────────────────────┼────────┼─────────╢
║ 2 │ Mon, 18 Dec 2017 16:08:31 UTC +00:00 │ Mon, 18 Dec 2017 17:08:31 UTC +00:00 │ "spam" │ "bacon" ║
╟────┼───────────────────────────────────────┼──────────────────────────────────────┼────────┼─────────╢
║ 3 │ Mon, 18 Dec 2017 16:08:30 UTC +00:00 │ Mon, 18 Dec 2017 17:08:30 UTC +00:00 │ "ham" │ "eggs" ║
╚════╧═══════════════════════════════════════╧══════════════════════════════════════╧════════╧═════════╝
在上面的例子中,所有的记录有重叠的时间,其中重叠只是意味着时间的范围内定义的记录的start_time
和end_time
(含)覆盖或延伸的一部分另一个记录。但是,对于这个问题,我们不仅对那些有重叠时间的记录感兴趣,而且还有匹配的bar
和baz
列(上面的行0,1和3)。在找到这些记录后,我们希望最早删除所有记录,仅留下记录2和3的表格,因为记录2没有匹配的bar
和baz
列,而且3具有最早的开始和结束时间。
这是我到目前为止有:
delete from foos where id in (
select
foo_one.id
from
foos foo_one
where
user_id = 42
and exists (
select
1
from
foos foo_two
where
tsrange(foo_two.start_time::timestamp, foo_two.end_time::timestamp, '[]') &&
tsrange(foo_one.start_time::timestamp, foo_one.end_time::timestamp, '[]')
and
foo_one.bar = foo_two.bar
and
foo_one.baz = foo_two.baz
and
user_id = 42
and
foo_one.id != foo_two.id
)
);
感谢您的阅读!
更新:我发现,对我工作的解决方案,基本上我可以申请窗口函数row_number()
在由bar
和baz
领域分组,则该表的分区添加WHERE
条款的DELETE
声明不包括第一个条目(最小的那个)id
。
delete from foos where id in (
select id from (
select
foo_one.id,
row_number() over(partition by
bar,
baz
order by id asc)
from
foos foo_one
where
user_id = 42
and exists (
select
*
from
foos foo_two
where
tsrange(foo_two.start_time::timestamp,
foo_two.end_time::timestamp,
'[]') &&
tsrange(foo_one.start_time::timestamp,
foo_one.end_time::timestamp,
'[]')
and
foo_one.id != foo_two.id
)
) foos where row_number <> 1
);
请编辑您的问题,并添加一些[样本数据](http://plaintexttools.github.io/plain-text-table/)和基于该数据的预期输出。 [格式化文本](http://stackoverflow.com/help/formatting)请,[无屏幕截图](http://meta.stackoverflow.com/questions/285551/why-may-i-not-upload-images -of码上那么当灰化-A-问题/ 285557#285557)。 – klin
我很好奇它为什么被标记为ruby-on-rails – jvillian
因为它是用于RoR项目的,并且我不希望人们在上面的查询中遇到ruby样式的字符串插值。 – dynsne