2

基本的な質問

Postgres 9.2 で、2 つのテーブルからデータを集計するビューを作成する方法はありますか?

必要なロジックは次のとおりです。

  1. 1 つのテーブルのデータが他のテーブルよりも優先される
  2. key同じ(複数のフィールドの組み合わせ) を持つ後続の行は、前の行を上書きします。
  3. D指定された「キー」の前の行を削除するステータスの行。

詳細と例

Postgres データベースに 2 つのスキーマがあります。それぞれのテーブルと列は同じですが、データは異なります。1 つは公式データ用で、もう 1 つは提案された変更用です。

注: もっと良い方法があると思いますが、これは従来の設定であり、変更できません。これは非常に単純化された架空の例ですが、必要な状況と結果を示しています。

したがって、ウィジェットを説明する特性の表があります。公式データには各タイプのデータが 1 つしかありません (ウィジェットには 1 つのサイズ、1 つの色などがあります)。

提案された変更が承認されると、公式データが変更されます。特定のタイプのデータに対して複数の保留中の変更が存在する場合があります。

officialスキーマ

CREATE TABLE characteristics (
    widget_id      integer NOT NULL,
    variation_id   integer NOT NULL,
    value          varchar(10),
    action_date    date,
    status         char(1)
);

のサンプル データofficial.characteristics:

1,1,GI Joe,12/25/2012,C
1,2,Green,12/25/2012,C
1,3,M,12/25/2012,C
1,4,Plastic,12/25/2012,C
2,1,GI Joe,12/25/2012,C
2,2,Green,12/25/2012,C
2,3,L,12/25/2012,C
2,4,Plastic,12/25/2012,C

2 つのウィジェットがあり、1 つはミディアム、グリーン、プラスチックです。1 つは大きく、緑色で、プラスチック製です。

proposedスキーマ

CREATE TABLE characteristics (
    widget_id      integer NOT NULL,
    variation_id   integer NOT NULL,
    value          varchar(10),
    action_date    date,
    status         char(1)
);

のサンプル データproposed.characteristics:

1,2,Blue,2/22/2013,C
1,4,Plastic,2/22/2013,D
2,2,Purple,2/10/2013,C
2,2,Green,2/22/2013,D
2,3,XL,2/22/2013,C

提案されたすべての変更の結果がどうなるかを確認したい場合は、古いデータを新しいデータに置き換えるか、以前のデータを削除する D 行を使用して、両方のテーブルにクエリを実行できます。

SELECT
  'o' as src,
  lpad(widget_id::text,4,'0'::text) || '_' || lpad(variation_id::text,4,'0'::text) as key,
  *
FROM
  proposed.characteristics
ORDER BY
  key ASC,
  action_date::date ASC

2 番目のクエリは同じですが、別のテーブルで、src として 'p' を使用します。

keyPHP を使用して、最初に公式、次に提案された変更を各テーブルにクエリし、 ( widget_id || '_' || variation_id) をキーとしてデータを配列に入れることができます。新しい行は古い行を上書きします。statusが(削除)の場合D、キーを持つ行が削除されます (ただし、その後の提案された変更によって再度追加される場合があります)。

したがって、上記のデータの場合、次のようになります。

o,0001_0001,1,1,GI Joe,12/25/2012,C
p,0001_0002,1,2,Blue,2/22/2013,C
o,0001_0003,1,3,M,12/25/2012,C
o,0002_0001,1,1,GI Joe,12/25/2012,C
p,0002_0003,2,3,XL,2/22/2013,C
o,0002_0004,2,4,Plastic,12/25/2012,C

概要

上記の結果を直接クエリできるビューを作成する方法はありますか?
そしてD、削除作業がまだ残っていて、新しい変更が以前の変更または公式データを上書きしますか?

4

1 に答える 1

1

情報が不足しているため、現行バージョンの PostgreSQL 9.2 を想定しています。

これを行う 1 つの方法は、両方のテーブルのCTEを使用し、反半結合UNION ALLを使用して各ウィジェットの最新の有効なバージョンを取得することです。NOT EXISTS

CREATE VIEW my_viw AS
WITH x AS (
   SELECT 'o' as src, * FROM official.characteristics
   UNION ALL
   SELECT 'p' as src, * FROM proposed.characteristics
   )
SELECT lpad(widget_id::text, 4, '0')
       || '_' || lpad(variation_id::text, 4, '0') AS key, * -- pick columns
FROM   x
WHERE  NOT EXISTS (
   SELECT 1 FROM x y
   WHERE  y.widget_id = x.widget_id
   AND    y.variation_id = x.variation_id
   AND    y.action_date > x.action_date
   )
AND   (status <> 'D' OR status IS NULL)
ORDER  BY widget_id, variation_id

コメントで指摘した間違いを除いて、概説した結果を返します。

->sqlfiddle

一歩一歩

  1. UNION ALLCTE でシンプルかつ高速に両方のテーブルからすべての行をフェッチする
  2. 同じ (widget_id、variation_id) の後の行が存在する行を除外します。NOT EXISTS
  3. で行を除外しますstatus = 'D'
  4. ORDER BY とからキーを合成しますwidget_id, variation_id

主なポイント

  • 元の列で操作し、最終的にwidget_id, variation_idのみ合成する方がおそらく高速です。コードが少なくなり、索引付けが容易になります。keySELECT

  • 結果は 2 つの場所で必要になるため、CTE を使用します。

  • statusを定義する必要がありますNOT NULL。これにより、WHERE 条件がより簡単になります。

  • 両方のテーブルで次のような複数列のインデックスを使用すると、パフォーマンスが向上する場合があります。の後に使用できるかどうかはわかりませんUNION ALL。でテストしEXPLAIN ANALYZEて確認してください。

    CREATE INDEX characteristics_mult_idx
    ON official.characteristics (widget_id, variation_id, action_date DESC) 
    
于 2013-02-22T21:32:59.477 に答える