[pgsql-jp: 37819] Re: 階級ごとの最大値や最小値の取り出し方を教えてください

渋谷泰宏 yasuhiro_shibutani @ ybb.ne.jp
2006年 12月 19日 (火) 11:01:39 JST


渋谷です。

#ちょっと長いですが・・・

■ 出力イメージを以下のものとします。

pt_grp   | ckの最大値 | ckの最小値 | ckの平均値 | データ数
-------------+------------+------------+------------+----------
-10以上0未満 | NULL   | NULL   | NULL   | 0
0以上10未満  | 4          | 2          | 3          | 2
10以上20未満 | 5          | 5          | 5          | 1

※ pt_grp 列はクエリではとりあえず左側の数値のみ出力する。

■ クエリを見やすくするため3つビューを作成するとします。

/* 1. pt 列を加工した pt_grp 列を持つ擬似テーブル */
CREATE OR REPLACE VIEW "usr_pt_grp" (
  id, usr_id, pt, pt_grp
) AS
SELECT id, usr_id, pt,
  ((CASE WHEN (pt>=0) THEN pt ELSE (pt-9) END) / 10 * 10)
FROM usr_pt;

# 加工方法を少し変更しています。

/* 2. usr_pt_grp と usr_ck の結合ビュー */
CREATE OR REPLACE VIEW "usr_pt_ck" (
  id, usr_id, pt, pt_grp, chkdate, ck
) AS
SELECT PG.id, PG.usr_id, PG.pt, PG.pt_grp, CK.chkdate, CK.ck
FROM usr_pt_grp AS PG
INNER JOIN usr_ck AS CK
  ON PG.usr_id = CK.usr_id;

/* 3. pt_grp の擬似マスタ テーブル */
CREATE OR REPLACE VIEW "pt_grp" (
  pt_grp
) AS
SELECT pt_grp
FROM usr_pt_grp
GROUP BY pt_grp;


> 1.出力イメージの識別列を左に外部結合する。

基準となる最も左の IDENTITY 列が分からないのですが、
これを出力イメージの pt_grp 列だとすると、こういうことです。

SELECT
  PG.pt_grp,
  max(PC.ck) AS ck_max,
  min(PC.ck) AS ck_min,
  avg(PC.ck) AS ck_avg,
  count(PC.ck) AS ck_cnt
FROM pt_grp AS PG
LEFT OUTER JOIN (
  SELECT pt_grp, ck
  FROM usr_pt_ck
  WHERE chkdate='2006-12-17'
) AS PC ON PC.pt_grp = PG.pt_grp
GROUP BY PG.pt_grp
ORDER BY PG.pt_grp;


> 2.集計元のデータに列を加える。

こっちは IDENTITY を pt_grp 列にすると例の記述と少し変わりますが、
こんな感じです。

SELECT
  PC.pt_grp,
  max(PC.ck) AS ck_max,
  min(PC.ck) AS ck_min,
  avg(PC.ck) AS ck_avg,
  count(PC.ck) AS ck_cnt
FROM (
    SELECT pt_grp, ck
    FROM usr_pt_ck
    WHERE chkdate='2006-12-17'
      UNION ALL
    SELECT pt_grp, NULL
    FROM pt_grp
) AS PC
GROUP BY PC.pt_grp
ORDER BY PC.pt_grp;

両者とも NULL でなく 0 の方が都合が良ければ coalesce でも使う。
後者の良いところは結合が一つ減ることでしょうか。

-- 
渋谷 泰宏



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