1. 程式人生 > 其它 >解決報錯:must appear in the GROUP BY clause or be used in an aggregate function

解決報錯: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#

搜尋

複製