1

次のレコードを持つ tracker という名前のテーブルがあるとします。

issue_id  |  ingest_date         |  verb,status
10         2015-01-24 00:00:00    1,1
10         2015-01-25 00:00:00    2,2
10         2015-01-26 00:00:00    2,3
10         2015-01-27 00:00:00    3,4
11         2015-01-10 00:00:00    1,3
11         2015-01-11 00:00:00    2,4

次の結果が必要です

10         2015-01-26 00:00:00    2,3
11         2015-01-11 00:00:00    2,4

このクエリを試しています

select * 
from etl_change_fact 
where ingest_date = (select max(ingest_date) 
                     from etl_change_fact);

しかし、これは私だけを与えます

10    2015-01-26 00:00:00    2,3

この記録。

しかし、すべての一意のレコード(change_id)が必要です

(a) max(取り込み日) AND

(b) 動詞列の優先度は (2 - 最初の優先度、1 - 2 番目の優先度、3 - 最後の優先度)

したがって、次の結果が必要です

10    2015-01-26 00:00:00    2,3
11    2015-01-11 00:00:00    2,4

効率的にクエリを実行するのを手伝ってください。

PS : 分散コンピューティングのセットアップで「配布キー」として設定するため、ingest_date のインデックスを作成しません。私はデータ ウェアハウスとクエリの初心者です。

したがって、TB サイズの DB をヒットするための最適化された方法を教えてください。

4

1 に答える 1

1

これは、典型的な「グループあたり最大 n」の問題です。ここでこのタグを検索すると、MySQL を含む多くのソリューションが得られます。

Postgres の場合、これを行う最も簡単な方法はdistinct on(これは、SQL 言語に対する Postgres 独自の拡張機能です)を使用することです。

select distinct on (issue_id) issue_id, ingest_date, verb, status
from etl_change_fact
order by issue_id, 
         case verb 
            when 2 then 1 
            when 1 then 2
            else 3
         end, ingest_date desc;

元のクエリを拡張して、相互に関連するサブクエリを使用して同じことを実現できます。

select f1.* 
from etl_change_fact f1
where f1.ingest_date = (select max(f2.ingest_date) 
                        from etl_change_fact f2
                        where f1.issue_id = f2.issue_id);

編集

古くてサポートされていない Postgres バージョンの場合、おそらく次のような方法で回避できます。

select f1.* 
from etl_change_fact f1
where f1.ingest_date = (select f2.ingest_date
                        from etl_change_fact f2
                        where f1.issue_id = f2.issue_id
                        order by case verb 
                                  when 2 then 1 
                                  when 1 then 2
                                  else 3
                              end, ingest_date desc
                        limit 1);

SQLFiddle の例: http://sqlfiddle.com/#!15/3bb05/1

于 2015-02-03T11:50:16.160 に答える