我有一個包含一個數據集:PostgreSQL和連續數據
Table { date itemName }
大部分的日期是連續的。沒有重複的日期[因爲它是主鍵]。
問題是分成多個部分(全部相對於使用SQL):
- 是否有可能找到在表中列出的日期串聯間隙? 例如:日期
1/2/09-1/3/09
不見了 - 是否有可能找到從表中缺少的日期部分,其範圍大於n(這是一個在運行時確定的數字)?例如:對於
n = 2
日期1/2/09-1/3/09
不返回,但日期5/6/09-6/1/09
是。
我有一個包含一個數據集:PostgreSQL和連續數據
Table { date itemName }
大部分的日期是連續的。沒有重複的日期[因爲它是主鍵]。
問題是分成多個部分(全部相對於使用SQL):
1/2/09-1/3/09
不見了n = 2
日期1/2/09-1/3/09
不返回,但日期5/6/09-6/1/09
是。只需在plsql或客戶端中創建一個函數,該函數將檢查所有日期。像這樣的僞碼:
date checked_date = 2000-01-01;
int unchecked_section = 0;
while (checked_date <= today()) {
if (! sql(select itemName from Table where itemName=checked_date)) {
unchecked_section++;
} else {
if (unchecked_section>=n) {
print checked_date-unchecked_section, checked_date
}
unchecked_section = 0;
}
checked_date++;
}
if (unchecked_section) {
print checked_date-unchecked_section, checked_date
}
它不一定非常快,因爲它只是維護。沒有太多的日期需要檢查 - 每年只有365個。
如果您沒有可用的SQL窗口函數,這種方法實際上是大型數據集上可能的最快速度,因爲它只能在表格上傳遞一次。你需要注意的一件事是SELECT獲取ORDER BY,以便行以排序順序出現。你應該使用「SELECT min(date),max(date)from table」得到循環限制 - 假設事物以'今天'結束並不是最好的主意。 PostgreSQL有很多可以在數據庫中運行的編程語言,PL/pgSQL是標準的。 – 2009-10-06 06:34:35
一些測試後,我想出了下面的SQL語句:
SELECT date, itemName
FROM "Table" as t1
WHERE NOT EXISTS (
SELECT date
FROM "Table" as t2
WHERE t2.date = (t1.date - INTERVAL '1 day')
)
ORDER BY date
OFFSET 1 -- this will skip the first element
這將讓你有沒有直接的繼任者都行。
如果修改了聲明:
SELECT date, itemName
FROM "Table" as t1
WHERE NOT EXISTS (
SELECT date
FROM "Table" as t2
WHERE (t2.date >= (t1.date - INTERVAL '2 day'))
AND (t2.date < t1.date)
)
ORDER BY date
OFFSET 1
可以使用的時間間隔長的子查詢的WHERE子句中至少這種規模的差距進行過濾。
希望有所幫助。
它的運行時間與表大小的平方成正比,因爲外部SELECT和內部EXISTS子查詢都處理其運行時與表大小成比例的事情。起初看似合理,但最終會變得非常昂貴。不幸的是,你在直接SQL中執行的任何其他解決方案都會遇到同樣的問題,因爲SQL沒有行內存。對於一個n行表,你必須通過某種方式來解決這類問題。如果可用,窗口功能是最好的。 – 2009-10-06 06:30:08
@Greg:感謝您的分析。你是對的,這不是最快的解決方案,如果Windows功能在手。但PostgreSQL 8.4是一個相當新鮮的版本,所以有機會,OP使用的是舊版本。 另請參閱OP對其運行時性能要求的問題的評論。 – 2009-10-06 07:41:39
如果你可以使用PostgreSQL 8.4則window functions將幫助:
SELECT *
FROM (SELECT itemName, date, date - lag(date) OVER w AS gap
FROM someTable WINDOW w AS (ORDER BY date)
) AS pairs
WHERE pairs.gap > '1 day'::interval;
這正是窗口函數打算有效解決的問題,並且沒有其他只能運行SQL的解決方案。 – 2009-10-06 06:24:35
不幸的是,我沒有版本8.4。我有8.1。我希望我能得到這個答案的功勞。我很喜歡。 – monksy 2009-10-23 02:07:16
我的做法是進行後處理的結果.. http://jeremy.zawodny.com/blog/archives/010523.html ..但如果在查詢內部是可能的,並且不會太糟糕地敲擊系統,那會很棒:) – warren 2009-10-05 01:56:43
這不是一個經常使用的實時查詢,它只是用於每次維護和一會兒。 – monksy 2009-10-05 02:06:39