| home | prev | next |
|---|
例えば次の様なテーブルがあり、
create table item
(
code char(8) constraint firstkey primary key,
name varchar(64) not null,
price int,
count int
);
その中に
| code | name | price | count |
|---|---|---|---|
| 01011001 | りんご | 100 | 5 |
| 01011002 | みかん | 100 | 5 |
| 01011003 | いちご | 100 | 10 |
| 01011004 | ばなな | 100 | 5 |
| 01011005 | かき | 100 | 1 |
| 01011006 | メロン | 300 | 1 |
というデータがあったとします。
price が 100円のレコード数と 300円のレコード数を個別に集計する時、どのような SQLを発行しますか?
レコード数を数えるなら通常 count関数を使用すると思います。
select count(price) from item where price = 100;
select count(price) from item where price = 300;
price が 100円と 300円のレコード数なのでと上記の様に二回 SQLを発行するか、
select
A.百円,
B.三百円
from
(select count(price) as 百円 from item where price = 100) A,
(select count(price) as 三百円 from item where price = 300) B
と結合するか、
select count(price) from item where price = 100
union
select count(price) from item where price = 300;
などと色々ありますが、何れも itemテーブルを 2回スキャンすることに変わりはありません。
ところが、case when then 〜 end を使用した場合、itemテーブルは 1回しかスキャンすることはありません。
select
coalesce(sum(case when price = 100 then 1 else 0 end), 0) as 百円,
coalesce(sum(case when price = 300 then 1 else 0 end), 0) as 三百円
from item;
explain analyze で確認してみてください。違いに驚きます。
因みに Oracle では同等の機能は decode という関数で提供されているようです。
| home | prev | next |
|---|