PostgreSQL相当于MySQL GROUP BY

时间:2012-05-01 13:41:36

标签: mysql sql postgresql group-by aggregate-functions

我需要在表格中找到重复项。在MySQL中我只写:

SELECT *,count(id) count FROM `MY_TABLE`
GROUP BY SOME_COLUMN ORDER BY count DESC

这个查询很好:

  • 根据SOME_COLUMN查找重复项,并重复计算。
  • 按重复顺序排序,这对快速扫描主要副本非常有用。
  • 为所有剩余列选择一个随机值,让我了解这些列中的值。

Postgres中的类似查询给我一个错误:

  

列“MY_TABLE.SOME_COLUMN”必须出现在GROUP BY子句中或者是   用于聚合函数

该查询的Postgres等价物是什么?

PS:我知道MySQL的行为偏离了SQL标准。

4 个答案:

答案 0 :(得分:12)

Back-ticks是一种非标准的MySQL东西。使用规范的双引号引用标识符(也可以在MySQL中引用)。也就是说,如果您的表实际上被命名为"MY_TABLE"(全部大写)。如果你(更明智地)将它命名为my_table(全部小写),那么你可以删除双引号或使用小写。

另外,我使用ct而不是count作为别名,因为将函数名称用作标识符是不好的做法。

简单案例

这适用于PostgreSQL 9.1

SELECT *, count(id) ct
FROM   my_table
GROUP  BY primary_key_column(s)
ORDER  BY ct DESC;

它需要GROUP BY子句中的主键列。结果与MySQL查询相同,但ct始终为1(如果id IS NULL则为0) - 无法查找重复项。

除主键列以外的分组

如果您想按其他列分组,事情会变得更复杂。此查询模仿MySQL查询的行为 - 您可以使用*

SELECT DISTINCT ON (1, some_column)
       count(*) OVER (PARTITION BY some_column) AS ct
      ,*
FROM   my_table
ORDER  BY 1 DESC, some_column, id, col1;

这是有效的,因为DISTINCT ON(特定于PostgreSQL),如DISTINCT(SQL-Standard),在窗口函数count(*) OVER (...)之后应用Window functions(带有OVER子句)需要PostgreSQL 8.4 或更高版本,并且在MySQL中不可用。

适用于任何表格,无论主要或唯一约束如何。

1DISTINCT ON中的ORDER BY只是简短地引用SELECT列表中项目的序号。

SQL Fiddle并肩展示。

这个密切相关答案的更多细节:


count(*)count(id)

如果您要查找重复项,最好使用count(*)而不是使用count(id)。如果id可以是NULL,则会有一个细微差别,因为NULL值不计算 - 而count(*)计算所有行。如果id定义为NOT NULL,则结果相同,但count(*)通常更合适(也会更快)。

答案 1 :(得分:3)

这是另一种方法,使用DISTINCT ON:

select 

  distinct on(ct, some_column) 

  *,
  count(id) over(PARTITION BY some_column) as ct

from my_table x
order by ct desc, some_column, id

数据来源:

CREATE TABLE my_table (some_column int, id int, col1 int);

INSERT INTO my_table  VALUES
 (1, 3,  4)
,(2, 4,  1)
,(2, 5,  1)
,(3, 6,  4)
,(3, 7,  3)
,(4, 8,  3)
,(4, 9,  4)
,(5, 10, 1)
,(5, 11, 2)
,(5, 11, 3);

输出:

SOME_COLUMN ID          COL1        CT
5           10          1           3
2           4           1           2
3           6           4           2
4           8           3           2
1           3           4           1

实时测试:http://www.sqlfiddle.com/#!1/e2509/1

DISTINCT ON文档:http://www.postgresonline.com/journal/archives/4-Using-Distinct-ON-to-return-newest-order-for-each-customer.html

答案 2 :(得分:1)

mysql允许group by 省略来自group by列表的非聚合选定列,它通过返回找到的第一行行来执行按列分组的每个唯一组合。这是非标准的SQL行为。

另一方面,postgres符合SQL标准。

postgres中没有等效的查询。

答案 3 :(得分:1)

这是一个自我加入的CTE,允许您使用select *。 key0是预期的唯一键,{key1,key2}是解决当前非唯一行所需的其他关键元素。使用YMMV需要您自担风险。

WITH zcte AS (
        SELECT DISTINCT tt.key0
        , MIN(tt.key1) AS key1
        , MIN(tt.key2) AS key2
        , COUNT(*) AS cnt
        FROM ztable tt
        GROUP BY tt.key0
        HAVING COUNT(*) > 1
        )
SELECT zt.*
        , zc.cnt AS cnt
FROM ztable zt
JOIN zcte zc ON zc.key0 = zt.key0 AND zc.key1 =  zt.key1 AND zc.key2 = zt.key2
ORDER BY zt.key0, zt.key1,zt.key2
      ;

BTW:要获得OP的预期行为,应省略HAVING COUNT(*) > 1子句。