1

住所データベースのかなり一般的なセットアップpersonがありcompanyます。companyaddress

すべてかなり正規化されており、使いやすいです。しかし、検索パフォーマンスのために、具体化された、むしろ非正規化されたビューを作成しています。非常に限られた一連の情報と簡単なクエリだけが必要です。結合テーブルを介して通常行われるすべてのことのほとんどが、配列に含まれるようになりました。クエリに応じて、直接検索するか、 経由で結合できますunnest

zipcodes私の列 ( )を補完するものとして、(ドイツ連邦) 州が既に事前計算されている列varchar[]を追加したいと考えています。これにより、すべての種類の範囲比較を含むようにクエリを変換する必要がなくなります。states

私のマッピング日は次のような表になっています。

CREATE TABLE zip2state (
    state TEXT NOT NULL,
    range_start CHARACTER VARYING(5) NOT NULL,
    range_end CHARACTER VARYING(5) NOT NULL
)

各州には複数の範囲があり、範囲が重複する場合があります (1 つの郵便番号が 2 つの異なる州に対応する場合があります)。一部の範囲にはrange_start = range_end.

今、私はそれを一度に具体化されたビューにする方法について少し頭が痛いです。通常、(トリガーを介して、またはアプリケーション レベルで) 反復的に実行したくなるでしょう。または、5桁について話しているだけなので、範囲を介して行うのではなく、zipを直接州にマッピングする大きなテーブルを作成できます(私の現在のお気に入りですが、何か良い方法があるかどうかを尋ねるほど醜いものです)

上記のようなテーブル(または同様のもの)を使用して、SQLでそれを行う方法はありますか?私はpostgres 9.3で、すべての機能が許可されています...

完全を期すために、郵便番号のサブクエリを次に示します。

    (select array_agg(distinct address.zipcode)
      from  affiliation
      join  company
        on  affiliation.ins_id = company.id
      join  address
        on  address.com_id = company.id
     where  affiliation.per_id = person.id) AS zipcodes,
4

1 に答える 1

1

LATERAL両方の列を一度に便利に計算するには、相関サブクエリの代わりに結合をお勧めします。次のようになります。

SELECT p.*, z.*
FROM   person p
LEFT   JOIN LATERAL (
   SELECT array_agg(DISTINCT d.zipcode) AS zipcodes
        , array_agg(DISTINCT z.state)   AS states
   FROM   affiliation    a
   -- JOIN   company     c ON a.ins_id = c.id  -- suspect you don't need this
   JOIN   address        d ON d.com_id = a.ins_id  -- c.id
   LEFT   JOIN zip2state z ON d.zipcode BETWEEN z.range_start AND z.range_end
   WHERE  a.per_id = p.id
   ) z ON true;

参照整合性が保証されている場合は、テーブルに結合する必要はまったくありませんcompany。私はショートカットを取った。

varcharまたはtextが数値に対して予想とは異なる動作をすることに注意してください。例: '333' > '0999'. すべての郵便番号が 5 桁の場合は問題ありません。

関連している:

于 2015-09-18T03:13:09.187 に答える