如何获取聚合函数选择的行的id? [复制]

Posted

技术标签:

【中文标题】如何获取聚合函数选择的行的id? [复制]【英文标题】:How to get id of the row which was selected by aggregate function? [duplicate] 【发布时间】:2019-03-04 04:57:36 【问题描述】:

我有下一个数据:

id | name | amount | datefrom
---------------------------
3  | a    |  8     | 2018-01-01
4  | a    |  3     | 2018-01-15 10:00
5  | b    |  1     | 2018-02-20

我可以将结果与下一个查询分组:

select name, max(amount) from table group by name

但我也需要所选行的id。因此我尝试了:

select max(id), name, max(amount) from table group by name

正如预期的那样,它会返回:

id | name | amount
-----------
4  | a    |  8
5  | b    |  1

但我需要3 的id 才能达到8 的数量:

id | name | amount
-----------
3  | a    |  8
5  | b    |  1

这可能吗?

PS。这是计费任务所必需的。在某一天,a2018-01-15 配置发生了更改,用户在 10 小时内消耗了一些资源,数量为 8,并在 14 小时内休息——3。我需要用最大值来计算这样的一天。因此,id = 4 的行在 2018 年 1 月 15 日被忽略。 (第二天2018-01-16我会开票3) 所以我采取对行计费:

3  | a    |  8     | 2018-01-01

如果它有问题。我必须报告id == 3 的那一行是错误的。

但是当我使用聚合函数时,id 的信息丢失了。

如果可以的话,那就太棒了:

select current(id), name, max(amount) from table group by name
select aggregated_row(id), name, max(amount) from table group by name

这里agg_row指的是被聚合函数max选中的行

UPD 我将任务解决为:

SELECT 
    (
       SELECT id FROM t2 
       WHERE id = ANY ( ARRAY_AGG( tf.id ) ) AND amount = MAX( tf.amount ) 
    ) id,
    name, 
    MAX(amount) ma,
    SUM( ratio )
FROM t2  tf
GROUP BY name

UPD 使用window functions会好很多

【问题讨论】:

关于您的更新:运算符为int = ANY(int[]),但DISTINCT ON 则不需要子查询。 @S-Man:请你写一下使用 SQL 的样子? 操作员在这个小提琴中演示:dbfiddle.uk/… 但如果不完全重建它,我真的无法让您的“更新”查询工作 - 有太多问题......这也是复杂:D @S-Man:谢谢。现在我修复我的查询。 Here是吗 【参考方案1】:

至少有3种方式,见下:

CREATE TEMP TABLE test (
    id integer, name text, amount numeric, datefrom timestamptz
);

COPY test FROM STDIN (FORMAT csv);
3,a,8,2018-01-01
4,a,3,2018-01-15 10:00
5,b,1,2018-02-20
6,b,1,2019-01-01
\.

方法 1. 使用 DISTINCT ON (PostgreSQL-specific)

SELECT DISTINCT ON (name)
  id, name, amount
FROM test
ORDER BY name, amount DESC, datefrom ASC;

方法2.使用窗口函数

SELECT id, name, amount FROM (
  SELECT *, row_number() OVER (
    PARTITION BY name
    ORDER BY amount DESC, datefrom ASC) AS __rn
  FROM test) AS x
WHERE x.__rn = 1;

方法3.使用关联子查询

SELECT id, name, amount FROM test
WHERE id = (
  SELECT id FROM test AS t2
  WHERE t2.name = test.name
  ORDER BY amount DESC, datefrom ASC
  LIMIT 1
); 

【讨论】:

【参考方案2】:

demo: db<>fiddle

您需要 DISTINCT ON 过滤每个组的第一行。

SELECT DISTINCT ON (name) 
    * 
 FROM table 
 ORDER BY name, amount DESC

【讨论】:

【参考方案3】:

您需要一个嵌套的内连接。试试这个 -

SELECT id, T2.name, T2.amount
FROM TABLE T
INNER JOIN (SELECT name, MAX(amount) amount
            FROM TABLE
            GROUP BY name) T2
ON T.amount = T2.amount

【讨论】:

当有 2 行名称相同、数量相同但日期和 ID 不同时,这将产生重复。

以上是关于如何获取聚合函数选择的行的id? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

hive聚合函数

SQL聚合函数选择唯一值

聚合函数&count&sum&avg&max&min

sql中的 开窗函数over() 聚合函数 排名函数

如何根据重复的行值合并聚合函数结果 | SQL 甲骨文

Hive之窗口函数