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

postgresql:如何从GROUPBY子句中获取主键?,sql,postgresql,group-by,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 u

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

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
,因为它是主键。。。对于初始(工作)查询返回的每一行,我确实需要主键和其余数据。

将原始查询用作子查询,并使用这些结果连接回原始表以查找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

由于您正在分组,因此每个返回的记录可以(并且很可能)有多个匹配的记录(例如,多个
id
value)

PostgreSQL非常严格——它不会猜测您的意思

  • 您可以运行子查询
  • 您可以基于
    b、c、d、e运行另一个查询
  • 您可以使用
    array\u agg
    分组函数来获取每个记录的
    id
    值数组
  • 见这个问题:

    我建议你把3作为最有效的可能性。


    希望这有帮助。谢谢

    将其添加到GROUPBY子句中是否有效

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

    如果你不在乎你得到的是哪个
    id
    ,那么你只需要将你的
    id
    封装在一个聚合函数中,这个聚合函数保证给你一个有效的
    id
    。我想到了
    max
    min
    聚合:

    -- 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;
    

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


    这不是您所要求的,但我怀疑您试图做的是获得与其他几列定义的每个组的一列的最大值对应的单行。例如,找到一整年中最热的星期一/星期二等

    我发现最好的方法是使用视图来查找组的所有最大值。如果你原来的桌子是

    create table T as (
      id integer primary key,
      a integer,
      b integer,
      c integer,
      d integer)
    
    然后创建“max”视图,如下所示

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

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

    我可以告诉postgres我想要任何给定的
    id
    记录,而我不在乎哪一条吗?(因为我没有)@Claudiu不应该这样。在(a,b,c,d,e)上添加一些索引可能会有所帮助。您是要获取具有最大a值的行的id,还是要获取具有b,c,d,e是否具有最大a值?@eviotto:初始查询返回的行的ID与原始查询返回的行不对应于数据库中的单个行。对于查询返回的每一行,可以有1个或多个对应的表行。@eviotto:我明白了。我正在尝试获取具有最大a值的行的id,yes@Claudiu:除非
    a
    是唯一的,否则可以有多行
    a
    最大值,因此有多个
    id
    符合条件。您知道这一点,对吗?请注意,此查询返回的行不一定是表中的行。@邪恶:这是一个好观点,可能是一个问题,具体取决于数据和“我想要任何给定的id记录,我不在乎哪一个?”的准确程度(请参阅对gahooa答案的评论)@ Eveloto:你能研究这是怎么回事吗?考虑行(99,1,1,1,1)和(1,99,1,1,1)- max(id)是99,max(a)是99,这个查询给出了两个MAX:(99,99,1,1,1)@邪恶:我认为一个窗口函数可能是更好的方法,我只是添加了一个可能性,如果你想双重检查。啊,是的,这确实是我想要的!我甚至没有意识到这不是我所要求的。。。
    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)