2009-10-05 9 views
5

は私が含まれているデータセットを持っています。日付の重複はありません(主キーと同じです)。PostgreSQLと順次データ

  1. それが表に記載された日付、一連のギャップを見つけることが可能です:

    質問は、(SQLを使用してに対するすべての)複数の部分に分割されますか? 例:日付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

+0

これは頻繁に使用されるライブクエリではなく、毎回のメンテナンスのためだけであり、しばらく。 – monksy

答えて

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ウィンドウ関数を使用できない場合、このアプローチは実際には大きなデータセットで可能な最速の方法です。テーブルを1回だけ通過するためです。あなたが見る必要があることの1つは、SELECTがORDER BYを取得し、行がソートされた順序で表示されることです。また、ループ制限を取得するには、 "SELECT min(date)、max(date)from table"を使用する必要があります。 PostgreSQLにはたくさんのプログラミング言語があり、データベースの中で実行することができます.PL/pgSQLは標準のものです。 –

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

この実行時間は、表のサイズの2乗に比例します。これは、外部SELECTと内部EXISTS副問合せの両方が実行時間が表のサイズに比例するためです。それは最初は妥当と思われるかもしれませんが、最終的には本当に高価になるでしょう。残念ながら、まっすぐなSQLで行う他のソリューションは、SQLに行メモリがないため、同じ問題が発生します。 n行のテーブルの場合、このタイプの問題を解決するには、n X nを何らかの方法で結合する必要があります。可能であれば、ウィンドウ機能がこれを中心に最適です。 –

+0

@Greg:分析をいただきありがとうございます。あなたが正しいです、これは最速の解決策ではありません、窓functiosが手近な場合。しかし、PostgreSQL 8.4は非常に新鮮なリリースなので、チャンスがあります、OPは古いバージョンを使用しています。 また、彼のランタイムパフォーマンス要件に関する彼の質問のOPコメントを見てください。 –

10

あなたはwindow functionsを助ける、その後のPostgreSQL 8.4を使用することができた場合:

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専用のソリューションは他にありません。 –

+0

残念ながら、バージョン8.4はありません。私は8.1を持っています。私はこの答えに功を奏したいと思う。私は本当にそれが好き。 – monksy