使用MAX和GROUP BY与公用表表达式(CTE)Postgresql

时间:2017-02-09 01:56:26

标签: sql database postgresql

我尝试使用WITH子句获取数据透视表,但我仍然坚持如何返回多个重复行使用MAX()

这是我的原始查询:

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             |

任何帮助将不胜感激,谢谢。

1 个答案:

答案 0 :(得分:1)

您的问题是您的GROUP BY子句指定的标准不够具体,无法满足您的需求。由于您只有一个采样日期,因此只能输出一行。

阅读您的输出,我您想要将hopper_name添加到GROUP BY条款中。但是,你并不是100%清楚自己要做什么,所以理解这个条款和其他替代方案可能很重要。

没有分组的GROUP BY

目前您正在做的事情。它基本上说,对于在此标准中唯一的每一行,返回一行。这可能就是你想要的。因此,请确保您在此处有GROUP BY完全符合您的要求。

替代方案:使用汇总和多维数据集进行分组设置

要注意的一个复杂解决方案是,PostgreSQL允许您根据条件设置多个分组集并进行汇总。如果ROLLUP无法让您到达目的地,那么可能想要查看CUBEGROUP BY。但是,这会使检索数据的过程变得复杂,因为您希望获得分组列的位图。但是,由于您正在尝试使用数据透视表,因此可能需要注意进一步的步骤(以及指向其他步骤)。