执行聚合函数时如何检索其他列?

Posted

技术标签:

【中文标题】执行聚合函数时如何检索其他列?【英文标题】:How to retrieve other columns when performing an aggregate function? 【发布时间】:2020-09-27 15:08:09 【问题描述】:

我一直在尝试从我正在执行聚合函数以按日期获取最小数量的表中检索其他列,这是数据的一个示例:

id   resource   date               quality   ask   ask_volume
1    1          2020-06-08 10:50   0         6.9   5102
2    1          2020-06-08 10:50   1         6.8   2943
3    1          2020-06-08 10:50   2         6.9   25338
4    1          2020-06-08 10:50   3         7.0   69720
5    1          2020-06-08 10:50   4         7.0   9778
6    1          2020-06-08 10:50   5         7.0   297435
7    1          2020-06-08 10:40   0         6.6   611
8    1          2020-06-08 10:40   1         6.6   4331
9    1          2020-06-08 10:40   2         6.7   1000
10   1          2020-06-08 10:40   3         7.0   69720
11   1          2020-06-08 10:40   4         7.0   9778
12   1          2020-06-08 10:40   5         7.0   297435
...

这是我想要得到的结果,所以我可以对其进行加权平均:

date               ask   ask_volume
2020-06-08 10:50   6.8   2943
2020-06-08 10:40   6.6   4331
...

虽然quality 0 和quality 1 都具有相同的ask,但应选择quality 1,因为它的ask_volume 更高。

我已经尝试过经典:

SELECT date, min(ask) FROM table GROUP BY date;

但是将ask_volume 添加到列列表会迫使我将其添加到GROUP BY,从而弄乱结果。

问题是:

    如何才能得到结果中显示的最小ask对应的ask_volume? 而且,如果在同一个date 上有两条具有相同ask 值的记录,如何让ask_volume 显示具有最高值的记录?

我使用 PostgreSQL,但来自不同数据库的 SQL 也可以帮助我理解这个想法。

【问题讨论】:

【参考方案1】:

在标准 SQL 中,您将使用窗口函数:

select *
from (
    select t.*, row_number() over(partition by date order by ask, ask_volume desc) rn
    from mytable 
) t
where rn = 1

在 Postgres 中,这更适合 distinct on

select distinct on (date) *
from mytable
order by ask, ask_volume desc

【讨论】:

【参考方案2】:

你可以用distinct on做你想做的事:

select distinct on (date) t.*
from (select t.*,
order by date, ask, ask_volume desc;

我发现您的 date 列令人困惑。它有一个时间成分,所以这个名字有误导性。

【讨论】:

【参考方案3】:

其他答案更简单、更好,但这里有一个解决聚合问题的替代方法。在获得 min 每个日期的询问之前,您可以使用子查询在每个询问的每个日期仅包含 max ask_volume。

select date, min(ask), max(ask_volume) 
from t
where (date, ask_volume) in (select date, max(ask_volume) 
                             from t
                             group by date, ask)
group by date;

【讨论】:

【参考方案4】:

DISTINCT ON 已被建议,但方式不完善。 (当前接受的答案是不正确的。)这就是你的做法:

SELECT DISTINCT ON (date) *
FROM   tbl
ORDER  BY date, ask, ask_volume DESC NULLS LAST;

最重要的是,ORDER BY 中的前导表达式必须在 DISTINCT ON 的表达式集中。换句话说,对于简单的情况,date 必须是第一个 ORDER BY 表达式。

虽然尚未排除 null 值(带有 NOT NULL 约束),但您必须按降序添加 NULLS LAST 或首先获取 null 值。

详细解释:

Select first row in each GROUP BY group?

【讨论】:

以上是关于执行聚合函数时如何检索其他列?的主要内容,如果未能解决你的问题,请参考以下文章

sql server中啥是聚合函数

如何检索时间范围聚合中的所有列?

group by语句,聚合函数与其他语句(关系,执行过程)

SQL Server聚合函数

SqlServer聚合函数

对跨标准和变体类型列的查询执行聚合函数