2009-10-05 164 views
5

我有一個包含一個數據集:PostgreSQL和連續數據

Table { date itemName } 

大部分的日期是連續的。沒有重複的日期[因爲它是主鍵]。

問題是分成多個部分(全部相對於使用SQL):

  1. 是否有可能找到在表中列出的日期串聯間隙? 例如:日期1/2/09-1/3/09不見了
  2. 是否有可能找到從表中缺少的日期部分,其範圍大於n(這是一個在運行時確定的數字)?例如:對於n = 2日期1/2/09-1/3/09不返回,但日期5/6/09-6/1/09是。
+0

我的做法是進行後處理的結果.. http://jeremy.zawodny.com/blog/archives/010523.html ..但如果在查詢內部是可能的,並且不會太糟糕地敲擊系統,那會很棒:) – warren 2009-10-05 01:56:43

+0

這不是一個經常使用的實時查詢,它只是用於每次維護和一會兒。 – monksy 2009-10-05 02:06:39

回答

1

只需在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個。

+0

如果您沒有可用的SQL窗口函數,這種方法實際上是大型數據集上可能的最快速度,因爲它只能在表格上傳遞一次。你需要注意的一件事是SELECT獲取ORDER BY,以便行以排序順序出現。你應該使用「SELECT min(date),max(date)from table」得到循環限制 - 假設事物以'今天'結束並不是最好的主意。 PostgreSQL有很多可以在數據庫中運行的編程語言,PL/pgSQL是標準的。 – 2009-10-06 06:34:35

1

一些測試後,我想出了下面的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子句中至少這種規模的差距進行過濾。

希望有所幫助。

+0

它的運行時間與表大小的平方成正比,因爲外部SELECT和內部EXISTS子查詢都處理其運行時與表大小成比例的事情。起初看似合理,但最終會變得非常昂貴。不幸的是,你在直接SQL中執行的任何其他解決方案都會遇到同樣的問題,因爲SQL沒有行內存。對於一個n行表,你必須通過某種方式來解決這類問題。如果可用,窗口功能是最好的。 – 2009-10-06 06:30:08

+0

@Greg:感謝您的分析。你是對的,這不是最快的解決方案,如果Windows功能在手。但PostgreSQL 8.4是一個相當新鮮的版本,所以有機會,OP使用的是舊版本。 另請參閱OP對其運行時性能要求的問題的評論。 – 2009-10-06 07:41:39

10

如果你可以使用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; 
+0

這正是窗口函數打算有效解決的問題,並且沒有其他只能運行SQL的解決方案。 – 2009-10-06 06:24:35

+0

不幸的是,我沒有版本8.4。我有8.1。我希望我能得到這個答案的功勞。我很喜歡。 – monksy 2009-10-23 02:07:16