解決報錯:must appear in the GROUP BY clause or be used in an aggregate function
阿新 • • 發佈:2022-05-18
今天使用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: SELECTcname, 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'
參考連結:
搜尋
複製