postgresql:如何从group by子句中获取主键?

时间:2011-10-28 21:06:11

标签: sql postgresql group-by

这是一个选择一组所需行的查询:

select max(a), b, c, d, e
from T
group by b, c, d, e;

该表在id列中有一个主键。

我想通过从每个行中获取主键来在另一个查询中标识这些行。我该怎么办?这不起作用:

select id, max(a), b, c, d, e
from T 
group by b, c, d, e;

ERROR:  column "T.id" must appear in the GROUP BY clause or be used in an aggregate function

我在其他一些postgresql问题中试过这个问题,但没有运气:

select distinct on (id) id, max(a), b, c, d, e
from T 
group by b, c, d, e;

ERROR:  column "T.id" must appear in the GROUP BY clause or be used in an aggregate function

我该怎么办?我知道每个结果只能有一个id,因为它是主键...我真的希望主键和其余数据一起,对于初始(工作)查询返回的每一行。

5 个答案:

答案 0 :(得分:5)

如果你不关心你得到哪个id那么你只需要将id包装在一些保证给你有效id的聚合函数中。我想到了maxmin聚合:

-- Or min(id) if you want better spiritual balance.
select max(id), max(a), b, c, d, e
from T 
group by b, c, d, e;

根据您的数据,我认为使用窗口功能将是一个更好的计划(感谢邪恶的otto引导到头部):

select id, a, b, c, d, e
from (
    select id, a, b, c, d, e, rank() over (partition by b,c,d,e order by a desc) as r
    from T
) as dt
where r = 1

答案 1 :(得分:3)

由于您分组这一事实,每个返回的记录可以(并且很可能)有多个匹配的记录(例如,多个id值)。

PostgreSQL非常严格 - 它不会猜到你的意思。

  1. 您可以运行子查询
  2. 您可以根据b,c,d,e
  3. 运行其他查询
  4. 您可以使用array_agg分组功能获取每条记录id值的数组。
  5. 请参阅此问题:Postgresql GROUP_CONCAT equivalent?

    我建议你认为#3是最有效的可能性。

    希望这会有所帮助。谢谢!

答案 2 :(得分:1)

将原始查询用作子查询,并使用这些结果连接回原始表以查找ID。

SELECT T.id, T.a, T.b, T.c, T.d, T.e
    FROM (SELECT max(a) AS MaxA, b, c, d, e
              FROM T
              GROUP BY b,c,d,e) q
        INNER JOIN T
            ON T.a = q.MaxA
                AND T.b = q.b
                AND T.c = q.c
                AND T.d = q.d
                AND T.e = q.e

答案 3 :(得分:1)

这不是你提出的问题,但我怀疑你要做的是让单行对应于由其他几列定义的每个组的一列的最大值。例如,找一整天的最热的星期一/星期二/等。

我发现这样做的最佳方法是使用视图查找组的所有最大值。如果您的原始表是

create table T as (
  id integer primary key,
  a integer,
  b integer,
  c integer,
  d integer)

然后将“max”视图创建为

create view T_maxgroups as 
  select max(a) as a, b, c, d 
  from T
  group by b, c, d

(这是您的初始查询)然后将该视图加入到您的表中以获取具有最大值的行:

select T.* from T join maxgroups using (a,b,c,d) 

答案 4 :(得分:0)

好奇的确是将它添加到group by子句的工作中吗?

select T.id, max(a), b, c, d, e
from T 
group by T.id b, c, d, e;