• 售前

  • 售后

热门帖子
入门百科

PostgreSQL对GROUP BY子句使用常量的特别限定详解

[复制链接]
敢想敢做敢拼 显示全部楼层 发表于 2021-8-14 15:07:22 |阅读模式 打印 上一主题 下一主题
一、问题形貌

近来,一个统计步伐从Oracle移植到PostgreSQL(版本9.4)时,接连陈诉错误:
  1. 错误信息1: postgresql group by position 0 is not in select list.
  2. 错误信息2: non-integer constant in GROUP BY.
复制代码
产生错误的sql类似于:
  1. insert into sum_tab (IntField1, IntField2, StrField1, StrField2, cnt)
  2. select IntField, 0, StrField, 'null', count(*) from detail_tab
  3. where ...
  4. group by IntField, 0, StrField, 'null';
复制代码
其中,detail_tab表保存原始的详细记载,而sum_tab保存统计后的记载信息。
二、原因分析

颠末测试,发现错误是由于PostgreSQL对GROUP BY子句使对使用常量有着特别限定。测试过程过于繁琐,这里不再逐一写demo了,直接给出结论:
1 GROUP BY子句中不能使用字符串型、浮点数型常量, 否则会陈诉错误信息2。如:
  1. select IntField, 'aaa', count(*) from tab group by IntField, 'aaa';
  2. select IntField, 0.5, count(*) from tab group by IntField, 0.5;
复制代码
2 GROUP BY子句中也不能使用0和负整数,否则会报错误信息1。如:
  1. select IntField, 0, count(*) from tab group by IntField, 0;
  2. select IntField, -1, count(*) from tab group by IntField, -1;
复制代码
那么,GROUP BY子句中可以使用什么类型的常量?经测试,在常用的类型中,正整数、日期型常量均可以。
  1. select IntField, 1, count(*) from tab group by IntField, 1;
  2. select IntField, now(), count(*) from tab group by IntField, now();
复制代码
对于第一节中的sql,由于0和‘null'有着特别的含义,该如那边理?
实际上,在GROUP BY子句中可以不使用任何常量,只列出聚集字段即可,即将第一节中的sql改为:
  1. insert into sum_tab (IntField1, IntField2, StrField1, StrField2, cnt)
  2. select IntField, 0, StrField, 'null', count(*) from detail_tab
  3. where ...
  4. group by IntField, StrField;
复制代码
三、MySQL的环境

思量到未来统计步伐也可能移植到MySQL(版本8.x),随后举行了类似测试,结论为:
1 支持不带任何常量的GROUP BY子句;
2 支持带非0整数、浮点数(包罗0.0)、字符串、日期型常量的GROUP BY子句。
也就是说,在常见类型中,MySQL 8的GROUP BY子句支持除整数0(非浮点数0.0)以外的全部类型。否则,会报错:
  1. ERROR 1054 (42S22): Unknown column '0' in 'group statement'
复制代码
顺便说一句,Oracle对整数0也支持。
四、结论

1、PostgreSQL的GROUP BY子句只支持正整数、日期型的常量;
2、MySQL支持除非0整数以外的全部常规类型常量,而Oracle似乎全部支持;
3、如果有在各各数据库平台可移植的需求,尽量不要在GROUP BY子句中使用常量。
补充:PostgreSQL的GROUP BY问题
关于PostgreSQL数据库分组查询时,跟mysql还是有区别的。纠结了半天
  1. SELECT
  2. prjnumber,
  3. zjhm,
  4. -- to_char ( to_timestamp ( kqsj / 1000 ), 'yyyy-MM-dd HH24:MI:SS' ) kqsj,
  5. kqflag,
  6. workername,
  7. max(kqsj)
  8. -- workertype,
  9. -- tpcodename,
  10. -- isactive
  11. FROM
  12. GB_CLOCKINGIN
  13. WHERE
  14. kqsj BETWEEN 1590940800000 AND 1593532799000
  15. AND prjnumber = '3205842019121101A01000'
  16. GROUP BY
  17. zjhm,
  18. kqflag,
  19. prjnumber,
  20. workername
复制代码
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未思量完全的地方,望不吝赐教。

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作