結合しない対象テーブル1個だけなら、GROUP BY 句と COUNT関数を使うが、
JOIN で結合したときの展開されるレコード数を求めるあるいは使用した
クエリはどうずれば良いか?
目的が、
結合元テーブルの任意カラムの数値 / 結合したときの展開されるレコード数
を1度のクエリで求めることである。
方法は2通りある。
(1)GROUP BYでカウントしたクエリと結合する方法
(2)ウィンドウ関数 OVER句を使って COUNTを求める方法
データベースが PostgreSQL で、以下のテーブルがあるとする。
CREATE TABLE items (
id int4 NOT NULL,
task_name varchar(60) NULL,
point int4 DEFAULT 0 NOT NULL,
CONSTRAINT items_pkey PRIMARY KEY (id)
)
CREATE TABLE itemcodes (
task_name varchar(60) NOT NULL,
task_code varchar(60) NULL
);
この items の task_name が、itemcode の task_name で結合しているとする。
求めたいのは、point が、 結合したときの展開されるレコード数で除算した値である。
(1)GROUP BYでカウントしたクエリと結合する方法
SELECT
a.task_name
,b.task_code
,a.point
,c.t_cnt
,ROUND(a.point * 1.0 / c.t_cnt, 6) AS a_value
FROM items a
LEFT JOIN itemcodes b ON a.task_name = b.task_name
INNER JOIN (
SELECT
task_name
,COUNT(task_name) AS t_cnt
FROM itemcodes
GROUP BY task_name
) c
ON b.task_name = c.task_name
ORDER BY a.task_name ASC
結合が増えて長くなるので良いとは思えない
(2)ウィンドウ関数 OVER句を使って COUNTを求める方法
SELECT
a.task_name
,b.task_code
,a.point
,COUNT(b.task_name) OVER (PARTITION BY b.task_name) AS t_cnt
,ROUND(a.point * 1.0 / COUNT(b.task_name) OVER (PARTITION BY b.task_name), 6) AS a_value
FROM items a
LEFT JOIN itemcodes b ON a.task_name = b.task_name
ORDER BY a.task_name ASC
OVER句で、結合カラムで区切ることを示す列をPARTITION BY で指定する。