解决报错:must appear in the GROUP BY clause or be used in an aggregate function

  今天使用Postgres数据库在编写sql 时,执行后发现报错:column "XXXXXX" must appear in the GROUP BY clause or be used in an aggregate function 根据提示把查询的字段放到分组后,查询的结果又不是自己需要的,在网上查询了一下解决方法,特此记录

  问题产生的原因:这是pgsql一个常见的聚合问题,在SQL3标准以前,选择显示的字段必须出现在在 GROUP BY 中

  假设存在makerar表,数据如下: 

 cname  | wmname |          avg           
--------+-------------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | luffy  | 1.00000000000000000000
 spain  | usopp  |     5.0000000000000000

   我想以cname分组查询到avg值最大的数据,sql如下

SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname;

  但是,报错

ERROR:  column "makerar.wmname" must appear in the GROUP BY clause or be used in an   aggregate function 
LINE 1: SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname;

  所以,我把wmname加入的分组后面

SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname, wmname;

  结果如下,但这不是我想要的数据

cname  | wmname |          max           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | luffy  | 1.00000000000000000000
 spain  | usopp  |     5.0000000000000000

  我想要的数据结果为

 cname  | wmname |          max           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | usopp  |     5.0000000000000000

  整理出两种方式解决该问题:

  一. 使用嵌套sql,在子查询中计算聚合,然后将其与自身连接,以获得需要显示的附加列

SELECT m.cname, m.wmname, t.mx
FROM (
    SELECT cname, MAX(avg) AS mx
    FROM makerar
    GROUP BY cname
    ) t JOIN makerar m ON m.cname = t.cname AND t.mx = m.avg
;

 cname  | wmname |          mx           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | usopp  |     5.0000000000000000

  二.使用特殊的DISTINCT ON表达式

SELECT DISTINCT ON (cname) 
    cname, wmname, avg
FROM 
    makerar 
ORDER BY 
    cname, avg DESC ;

  结合自身业务,使用第一种方式改造sql

    SELECT
        pihs.pat_status,
        b.bed_class_id,
        pih.charge_class_id,
        pihs.pat_condition,
        pih.pat_id,
        pihs.room_with_mother_baby_flag,
        pc.pat_in_charge_doc_name,
        pc.pat_in_charge_doc_id,
        b.bed_show_no,
        pih.pat_age AS age,
        pih.pat_in_hos_id,
        pih.pat_in_hos_code,
        pihs.pat_in_status,
        pc.state_of_critical_value,
        pih.pat_in_time,
        pc.chief_doc_id,
        pc.chief_doc_name,
        pc.dur_nurse_id,
        pc.dur_nurse_name,
        pc.first_ann_bed_time,
        pc.manage_bed_nurse_name,
        pih.pat_type_id,
        pc.pat_clinic_id,
        pc.pat_ward_id,
        b.bed_id,
        b.bed_status,
        b.is_share,
        pc.nursing_class,
        pc.nursing_class_name,
        pihs.pat_in_bed_share_status,
        pih.seven_days_again_in_flag,
        b.price,
        T.change_in_time
        FROM
        bed b
        LEFT JOIN pat_in_hospital_status pihs ON b.bed_id = pihs.bed_id
        LEFT JOIN pat_in_hospital pih ON b.pat_in_hos_id = pih.pat_in_hos_id
        LEFT JOIN pat_clinican pc ON pih.pat_in_hos_id = pc.pat_in_hos_id
        LEFT JOIN ( SELECT pat_in_hos_id, MAX ( pat_in_out_ward_time ) AS change_in_time FROM change_ward_record WHERE complete_flag = '1' GROUP BY pat_in_hos_id ) T ON pih.pat_in_hos_id = T.pat_in_hos_id
        where b.ward_id='1234'

参考链接:

https://stackoverflow.com/questions/19601948/must-appear-in-the-group-by-clause-or-be-used-in-an-aggregate-function#

 

posted @ 2022-05-18 14:56  青春的西瓜  阅读(34316)  评论(0编辑  收藏  举报