我試圖找出一種方法來刪除重疊時間的記錄,但我無法找出保持所有但這些記錄重疊的一個的簡單和優雅的方法。這個問題與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