2017-02-09 74 views
0

我試圖用WITH子句,以獲得數據透視表,但我卡在如何返回多個使用MAX()複製行。使用MAX和GROUP BY與通用表表達式(CTE的)PostgreSQL的

這是我原來的查詢:

SELECT b.detail_id, a.sampling_date, a.sampling_area, 
     b.sampling_point, b.sampling_type, 
     b.ha_tpc, b.ha_entero, b.ha_ecoli, b.ha_salmonella 
FROM tbl_header a 
    JOIN tbl_detail b ON a.headerid = b.headerid 
WHERE 
    a.sampling_date = '2016-12-09' AND 
    a.sampling_area = 'CMP' AND 
    (b.sampling_point ~* '.*(flex).*' OR b.sampling_point ~* '.*(HPM).*' OR b.sampling_point ~* '.*(fr).*') AND 
    (b.sampling_type = 'Personil' OR b.sampling_type = 'Equipment') 

這裏是結果:

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
detail_id | sampling_date | sampling_area |  sampling_point   | sampling_type | ha_tpc | ha_entero | ha_ecoli  | ha_salmonella | 
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
24243  | 2016-12-09 |  CMP   | BOIL013 (OPERATOR ENFLEX) | Personil  |  500  | 50  |  Abs  |  Abs   | 
24289  | 2016-12-09 |  CMP   | MP115 (OPR ENFLEX)   | Personil  |  300  | 50  |  Abs  |  Abs   | 
24284  | 2016-12-09 |  CMP   | WT033 (FR)     | Personil  |  250  | 50  |  Abs  |  Abs   | 

有了這些記錄,我試圖創建一個支點查詢類似如下:

WITH tmp_date AS (
    SELECT sampling_date.sampling_date::date AS sampling_date 
     FROM generate_series(
      (( 
       SELECT min(tbl_header.sampling_date) AS min 
       FROM tbl_header 
      ))::timestamp with time zone, 
      (( 
       SELECT max(tbl_header.sampling_date) AS max 
       FROM tbl_header 
      ))::timestamp with time zone, '1 day'::interval 
     ) sampling_date(sampling_date) 
), 

tmp_detail AS (
    SELECT a.sampling_date, a.sampling_area, 
      b.detail_id, b.sampling_point, b.sampling_type, 
      b.ha_tpc, b.ha_entero, b.ha_ecoli, b.ha_salmonella 
    FROM tbl_header a 
     JOIN tbl_detail b ON a.headerid = b.headerid 
), 

resulttable AS (
    SELECT tmp_date.sampling_date, tmp_detail.sampling_point, tmp_detail.sampling_type, 

     -- Case of Filling Room 
     CASE 
      WHEN tmp_detail.sampling_point ~* '.*(fr).*' AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.sampling_point 
      ELSE NULL 
     END AS fr_name, 
     CASE 
      WHEN tmp_detail.sampling_point ~* '.*(fr).*' AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.ha_tpc 
      ELSE NULL 
     END AS fr_tpc, 
     CASE 
      WHEN tmp_detail.sampling_point ~* '.*(fr).*' AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.ha_entero 
      ELSE NULL 
     END AS fr_entero, 
     CASE 
      WHEN tmp_detail.sampling_point ~* '.*(fr).*' AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.ha_ecoli 
      ELSE NULL 
     END AS fr_ecoli, 
     CASE 
      WHEN tmp_detail.sampling_point ~* '.*(fr).*' AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.ha_salmonella 
      ELSE NULL 
     END AS fr_salmo, 

     -- Case of Hopper Auger Filling 
     CASE 
      WHEN (tmp_detail.sampling_point ~* '.*(flex).*' OR tmp_detail.sampling_point ~* '.*(HPM).*') AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.sampling_point 
      ELSE NULL 
     END AS hpm_name, 
     CASE 
      WHEN (tmp_detail.sampling_point ~* '.*(flex).*' OR tmp_detail.sampling_point ~* '.*(HPM).*') AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.ha_tpc 
      ELSE NULL 
     END AS hpm_tpc, 
     CASE 
      WHEN (tmp_detail.sampling_point ~* '.*(flex).*' OR tmp_detail.sampling_point ~* '.*(HPM).*') AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.ha_entero 
      ELSE NULL 
     END AS hpm_entero, 
     CASE 
      WHEN (tmp_detail.sampling_point ~* '.*(flex).*' OR tmp_detail.sampling_point ~* '.*(HPM).*') AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.ha_ecoli 
      ELSE NULL 
     END AS hpm_ecoli, 
     CASE 
      WHEN (tmp_detail.sampling_point ~* '.*(flex).*' OR tmp_detail.sampling_point ~* '.*(HPM).*') AND tmp_detail.sampling_type = 'Personil' THEN tmp_detail.ha_salmonella 
      ELSE NULL 
     END AS hpm_salmo 

    FROM tmp_date 
     FULL JOIN tmp_detail ON tmp_date.sampling_date = tmp_detail.sampling_date 
    WHERE 
     tmp_detail.sampling_area = 'CMP' AND 
     tmp_detail.sampling_type = 'Personil' AND 
     (
      tmp_detail.sampling_point ~* ANY (VALUES ('(fr)'), ('(flex)'), ('(HPM)')) 
     ) 
) 

SELECT 
    resulttable.sampling_date, 
    max(resulttable.sampling_type) AS sampling_type, 

    max(resulttable.fr_name) AS fr_name, 
    max(resulttable.fr_tpc) AS fr_tpc, 
    max(resulttable.fr_entero) AS fr_entero, 
    max(resulttable.fr_ecoli) AS fr_ecoli, 
    max(resulttable.fr_salmo) AS fr_salmonella, 

    max(resulttable.hpm_name) AS hopper_name, 
    max(resulttable.hpm_tpc) AS hopper_tpc, 
    max(resulttable.hpm_entero) AS hopper_entero, 
    max(resulttable.hpm_ecoli) AS hopper_ecoli, 
    max(resulttable.hpm_salmo) AS hopper_salmonella 

FROM resulttable 
    GROUP BY resulttable.sampling_date ORDER BY resulttable.sampling_date; 

我不知道爲什麼這些查詢只返回1行,是不是因爲我用GROUP BY

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
sampling_date | sampling_type |   fr_name    | fr_tpc | fr_entero | fr_ecoli | fr_salmonella |   hopper_name   | hopper_tpc | hopper_entero | hopper_ecoli | hopper_salmonella | 
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
2016-12-09  |  Personil |  WT033 (FR)    | 250 | 50   |  Abs |  Abs   | BOIL013 (OPERATOR ENFLEX) |  500  |  50   |  Abs  |  Abs    | 

其實我是想得到的結果如下所示:

        =====================   Case of Filling Room   =========================== | =====================   Case of Hopper Auger Filling     ============================ 
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
sampling_date | sampling_type |   fr_name    | fr_tpc | fr_entero | fr_ecoli | fr_salmonella |   hopper_name   | hopper_tpc | hopper_entero | hopper_ecoli | hopper_salmonella | 
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
2016-12-09  |  Personil |  WT033 (FR)    | 250 | 50   |  Abs |  Abs   | BOIL013 (OPERATOR ENFLEX) |  500  |  50   |  Abs  |  Abs    | 
2016-12-09  |  Personil |        |   |    |   |     | MP115 (OPR ENFLEX)   |  300  |  50   |  Abs  |  Abs    | 

任何幫助,將不勝感激,謝謝。

+0

我想,你也需要通過'fr_name'和'hopper_name' – cha

回答

1

你的問題是,你的GROUP BY子句指定不適合你的需求不夠具體標準。由於您只有一個採樣日期,因此只有一行。

讀取您的輸出,我認爲您想添加hopper_name到GROUP BY條款。然而,它不是100%清楚你想要做什麼,所以理解這個條款和其他選擇可能是重要的。

GROUP BY不進行分組套

這是目前你在做什麼。它說,基本上,對於在此標準中唯一的每一行,返回一行。這可能是你想要的。因此,請確保您在此處具有GROUP BY,並完全參照您的要求。

替代方案:用分組彙總集和立方體

一個複雜的解決方案,需要注意的是,PostgreSQL允許你有多重分組基於標準捲起集一起。您可能想看看ROLLUPCUBE此,如果GROUP BY不把你帶到你想去的地方。但是,這在檢索數據時稍微複雜一些,因爲您想獲取分組列的位圖。但是,由於您正在嘗試執行數據透視表,因此可能值得注意進一步的步驟(以及其他指向)。

+0

非常感謝您爲您講解組,我已經改變了我的查詢,現在,它的工作原理是我想要的一切,我想我需要學習更多關於如何使用「GROUP BY」子句。 – metaphor