Hatena::Grouppostgresql

PostgreSQL 雑記 このページをアンテナに追加 RSSフィード

2010-09-03複数同時にcount() このエントリーを含むブックマーク このエントリーのブックマークコメント

1回の集計SQLで複数を同時に count() するときって、結構迷いませんか? 誰しも一度は、

=# SELECT count(i % 2 = 0), -- 2の倍数の数
          count(i % 3 = 0)  -- 3の倍数の数
     FROM generate_series(1, 100) AS t(i);
 count | count
-------+-------
   100 |   100   ← 失敗!
(1 row)

と count() 内に条件式を書いて、アレ?という経験はあるのでは。

そんなときは、count() は NULL を数えないことを利用しましょう。下記のように CASE を使うか (ELSE 省略時、一致する WHEN が無ければ NULL になります)

=# SELECT count(CASE WHEN i % 2 = 0 THEN 1 END), -- 1 の箇所は非NULLなら何でも良い
          count(CASE WHEN i % 3 = 0 THEN 1 END)
     FROM generate_series(1, 100) AS t(i);
 count | count
-------+-------
    50 |    33
(1 row)

もしくは nullif(..., false) を使う方法があります。

=# SELECT count(nullif(i % 2 = 0, false)),
          count(nullif(i % 3 = 0, false))
     FROM generate_series(1, 100) AS t(i);
 count | count
-------+-------
    50 |    33
(1 row)


ところで、true だけを数える count_if() があっても良いような気もします。いろいろひっくるめて、「C++ の STL アルゴリズムSQL でも!」なんていう奇特な方はいないのかな?

iakioiakio2010/09/07 00:00なるほど。sum(CASE WHEN...END)を使う方法は知ってましたがNULLを利用すればcount()でもいいんですね。
http://www.geocities.jp/mickindex/database/db_case.html

pgsqlpgsql2010/09/08 13:31逆に count(nullable_column) しないように気を付ける必要もありますね。
あと、単に数えるだけなら count(*) が最速なのもTIPSです。