PostgreSQL對(duì)GROUP BY子句使用常量的特殊限制詳解
一、問題描述
最近,一個(gè)統(tǒng)計(jì)程序從Oracle移植到PostgreSQL(版本9.4)時(shí),接連報(bào)告錯(cuò)誤:
錯(cuò)誤信息1: postgresql group by position 0 is not in select list.
錯(cuò)誤信息2: non-integer constant in GROUP BY.
產(chǎn)生錯(cuò)誤的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表保存原始的詳細(xì)記錄,而sum_tab保存統(tǒng)計(jì)后的記錄信息。
二、原因分析
經(jīng)過測試,發(fā)現(xiàn)錯(cuò)誤是因?yàn)镻ostgreSQL對(duì)GROUP BY子句使對(duì)使用常量有著特殊限制。測試過程過于繁瑣,這里不再一一寫demo了,直接給出結(jié)論:
1 GROUP BY子句中不能使用字符串型、浮點(diǎn)數(shù)型常量, 否則會(huì)報(bào)告錯(cuò)誤信息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和負(fù)整數(shù),否則會(huì)報(bào)錯(cuò)誤信息1。如:
select IntField, 0, count(*) from tab group by IntField, 0; select IntField, -1, count(*) from tab group by IntField, -1;
那么,GROUP BY子句中可以使用什么類型的常量?經(jīng)測試,在常用的類型中,正整數(shù)、日期型常量均可以。
select IntField, 1, count(*) from tab group by IntField, 1; select IntField, now(), count(*) from tab group by IntField, now();
對(duì)于第一節(jié)中的sql,因?yàn)?和‘null'有著特殊的含義,該如何處理?
實(shí)際上,在GROUP BY子句中可以不使用任何常量,只列出聚集字段即可,即將第一節(jié)中的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的情況
考慮到將來統(tǒng)計(jì)程序也可能移植到MySQL(版本8.x),隨后進(jìn)行了類似測試,結(jié)論為:
1 支持不帶任何常量的GROUP BY子句;
2 支持帶非0整數(shù)、浮點(diǎn)數(shù)(包括0.0)、字符串、日期型常量的GROUP BY子句。
也就是說,在常見類型中,MySQL 8的GROUP BY子句支持除整數(shù)0(非浮點(diǎn)數(shù)0.0)以外的所有類型。否則,會(huì)報(bào)錯(cuò):
ERROR 1054 (42S22): Unknown column '0' in 'group statement'
順便說一句,Oracle對(duì)整數(shù)0也支持。
四、結(jié)論
1、PostgreSQL的GROUP BY子句只支持正整數(shù)、日期型的常量;
2、MySQL支持除非0整數(shù)以外的所有常規(guī)類型常量,而Oracle似乎全部支持;
3、如果有在各各數(shù)據(jù)庫平臺(tái)可移植的需求,盡量不要在GROUP BY子句中使用常量。
補(bǔ)充:PostgreSQL的GROUP BY問題
關(guān)于PostgreSQL數(shù)據(jù)庫分組查詢時(shí),跟mysql還是有區(qū)別的。糾結(jié)了半天
SELECT prjnumber, zjhm, -- to_char ( to_timestamp ( kqsj / 1000 ), 'yyyy-MM-dd HH24:MI:SS' ) kqsj, kqflag, workername, max(kqsj) -- workertype, -- tpcodename, -- isactive FROM GB_CLOCKINGIN WHERE kqsj BETWEEN 1590940800000 AND 1593532799000 AND prjnumber = '3205842019121101A01000' GROUP BY zjhm, kqflag, prjnumber, workername
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
postgresql運(yùn)維之遠(yuǎn)程遷移操作
這篇文章主要介紹了postgresql運(yùn)維之遠(yuǎn)程遷移操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01PostgreSQL+GeoHash地圖點(diǎn)位聚合實(shí)現(xiàn)代碼
這篇文章主要介紹了PostgreSQL+GeoHash地圖點(diǎn)位聚合,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07postgresql 循環(huán)函數(shù)的簡單實(shí)現(xiàn)操作
這篇文章主要介紹了postgresql 循環(huán)函數(shù)的簡單實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01PostgreSQL的日期時(shí)間差DATEDIFF實(shí)例詳解
PostgreSQL是一款簡介而又性能強(qiáng)大的數(shù)據(jù)庫應(yīng)用程序,其在日期時(shí)間數(shù)據(jù)方面所支持的功能也都非常給力,下面這篇文章主要給大家介紹了關(guān)于PostgreSQL的日期時(shí)間差DATEDIFF的相關(guān)資料,需要的朋友可以參考下2023-04-04PostgreSQL 數(shù)據(jù)庫性能提升的幾個(gè)方面
PostgreSQL提供了一些幫助提升性能的功能。主要有一些幾個(gè)方面。2009-09-09PostgreSQL更新表時(shí)時(shí)間戳不會(huì)自動(dòng)更新的解決方法
這篇文章主要為大家詳細(xì)介紹了PostgreSQL更新表時(shí)時(shí)間戳不會(huì)自動(dòng)更新的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10postgresql數(shù)據(jù)庫配置文件postgresql.conf,pg_hba.conf,pg_ident.conf
這篇文章主要為大家介紹了postgresql數(shù)據(jù)庫中三個(gè)重要的配置文件postgresql.conf,pg_hba.conf,pg_ident.conf使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02