PostgreSQL對GROUP BY子句使用常量的特殊限制


一、問題描述

最近,一個統計程序從Oracle移植到PostgreSQL(版本9.4)時,接連報告錯誤:

錯誤信息1: postgresql group by position 0 is not in select list.

錯誤信息2: non-integer constant in GROUP BY.

產生錯誤的sql類似於:

insert into sum_tab (IntField1, IntField2, StrField1, StrField2, cnt)
select IntField, 0, StrField, 'null', count(*) from detail_tab
where ...
group by IntField, 0, StrField, 'null';

其中,detail_tab表保存原始的詳細記錄,而sum_tab保存統計后的記錄信息。

二、原因分析

經過測試,發現錯誤是因為PostgreSQL對GROUP BY子句使對使用常量有着特殊限制。測試過程過於繁瑣,這里不再一一寫demo了,直接給出結論:

1 GROUP BY子句中不能使用字符串型、浮點數型常量, 否則會報告錯誤信息2。如:

select IntField, 'aaa', count(*) from tab group by IntField, 'aaa'; 
select IntField, 0.5, count(*) from tab group by IntField, 0.5;

2 GROUP BY子句中也不能使用0和負整數,否則會報錯誤信息1。如:

select IntField, 0, count(*) from tab group by IntField, 0;
select IntField, -1, count(*) from tab group by IntField, -1;

那么,GROUP BY子句中可以使用什么類型的常量?經測試,在常用的類型中,正整數、日期型常量均可以。

select IntField, 1, count(*) from tab group by IntField, 1;
select IntField, now(), count(*) from tab group by IntField, now();

對於第一節中的sql,因為0和‘null’有着特殊的含義,該如何處理?

實際上,在GROUP BY子句中可以不使用任何常量,只列出聚集字段即可,即將第一節中的sql改為:

insert into sum_tab (IntField1, IntField2, StrField1, StrField2, cnt)
select IntField, 0, StrField, 'null', count(*) from detail_tab
where ...
group by IntField, StrField;

三、MySQL的情況

考慮到將來統計程序也可能移植到MySQL(版本8.x),隨后進行了類似測試,結論為:

1 支持不帶任何常量的GROUP BY子句;

2 支持帶非0整數、浮點數(包括0.0)、字符串、日期型常量的GROUP BY子句。

也就是說,在常見類型中,MySQL 8的GROUP BY子句支持除整數0(非浮點數0.0)以外的所有類型。否則,會報錯:

ERROR 1054 (42S22): Unknown column '0' in 'group statement'

順便說一句,Oracle對整數0也支持。

 四、結論

  1. PostgreSQL的GROUP BY子句只支持正整數、日期型的常量;
  2. MySQL支持除非0整數以外的所有常規類型常量,而Oracle似乎全部支持;
  3. 如果有在各各數據庫平台可移植的需求,盡量不要在GROUP BY子句中使用常量。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM