結合しない対象テーブル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 で指定する。