[pgsql-jp: 37605] Re: 1:n から 1:1 を抽出するSQL文

Toshihiro Kano kanout @ nttdata.co.jp
2006年 10月 22日 (日) 21:31:50 JST


かのうです。

> select X, Y from A, B
> where I=K and J in (select max(J) from B group by K ) ;
> として、解決しましたが、かのうさんのかかれたもので、最後の where
> bq,k=tb.k ですが、これのほうが効率的でしょうか?

> select ta.x,tb.y
> from tb inner join ta
> on tb.k=ta.i
> where tb.j=
> (select max(bq.j)
> from tb as bq
> where bq.k=tb.k);

以下のことは、PostgreSQLのプランナの動作を把握した上での
記載ではないことをご了承願います。

副問合せは、上手く使わないと性能が著しく劣化します。
副問合せとして単純にSELECT文を書くと、まずそのSELECT文を実
行してから、親の問合せを実行する手順になりそうな気がします。
ですので、テーブルB を一回アクセスしきった後に、再度JOIN演
算でアクセスすることになりそうで、二度手間の可能性がありま
す。

副問合せを、外のSELECT文と結んでやる(where bq.k=tb.k)と、
テーブルB のアクセスは、親の問合せから引継いだ範囲に限られ
ますから、バッファヒットの可能性が高くなります。また、商用
のDBMS等を用いた大規模なデータベースで、パーティション化さ
れている場合で、アクセスをパーティションの範囲に限定させる
等、分散を考慮する場合は、上記のような仕掛けが必要になりま
す。

もちろん、適切にインデックスが設定されている上での話です。

逆にテーブルB が全てバッファリング出来るサイズであれば、物
理IOに差異はないでしょうから、気にする必要はないと思います。

いずれにしても、それ相応の行数があり、統計情報を最新化した
上で、ANALYZE した結果でどちらのアクセスパスがコストが小さ
いか見なければ、全て想像の範囲の話です。


> ところで、sum()はマニュアルの例にありましたが、max()などはマニュアルのど
> こかに書かれているのでしょうか?

MAX関数は、集約関数の1つです。標準SQLですので、他のRDBMSで
も使えます。PostgreSQLも下記に記載がありますよ。
http://www.postgresql.jp/document/pg815doc/html/tutorial-agg.html




pgsql-jp メーリングリストの案内