Select group by 上每组的最大记录数
Select max record of each group on a group by
我正在使用 PostgreSQL。
我需要select每个组的max,情况是table代表每天销售的产品,我想知道销量最高的每天的产品。
SELECT sum(detalle_orden.cantidad) as suma,detalle_orden.producto_id as producto
,to_char(date_trunc('day',orden.fecha AT TIME ZONE 'MST'),'DY') as dia
FROM detalle_orden
LEFT JOIN orden ON orden.id = detalle_orden.order_id
GROUP BY orden.fecha,detalle_orden.producto_id
ORDER BY dia,suma desc
正在返回:
suma producto dia
4 1 FRI
1 2 FRI
5 3 TUE
2 2 TUE
我想得到:
suma producto dia
4 1 FRI
5 3 TUE
只有每天的顶级产品(每个组的max(suma)
)。
我尝试了不同的方法,比如子查询,但是使用的聚合函数让事情变得有点困难。
您可以(滥用)使用带有适当排序子句的 SELECT DISTINCT ON
。假设您将之前的查询放入视图中:
SELECT DISTINCT ON (dia, producto) * FROM some_view ORDER BY dia, producto, suma DESC;
DISTINCT
确保您只会为每一天和产品保留一行,ORDER BY
确保它保留正确的一行
通过窗口函数:RANK 可以轻松搞定:
select * from
(
select suma,producto,dia, rank() over (partition by dia order by suma desc) as ranking
from your_query
)A
where ranking = 1
所以你最终的查询将是这样的:
select * from
(
select suma,producto,dia, rank() over (partition by dia order by suma desc) as ranking
from
(
SELECT sum(detalle_orden.cantidad) as suma,detalle_orden.producto_id as producto,to_char(date_trunc
('day',orden.fecha AT TIME ZONE 'MST'),'DY') as dia FROM detalle_orden LEFT JOIN
orden ON orden.id= detalle_orden.order_id GROUP by
orden.fecha,detalle_orden.producto_id ) B
) A
where ranking = 1
您仍然可以使用 DISTINCT ON
在没有子查询的单个查询级别中完成此操作,因为 DISTINCT
在 GROUP BY
和聚合函数之后(以及在 window 函数):
SELECT DISTINCT ON (3)
sum(d.cantidad) AS suma
, d.producto_id AS producto
, to_char(o.fecha AT TIME ZONE 'MST', 'DY') AS dia
FROM detalle_orden d
LEFT JOIN orden o ON o.id = d.order_id
GROUP BY o.fecha, d.producto_id
ORDER BY 3, 1 DESC NULLS LAST, d.producto_id;
备注
此解决方案 returns 每个 dia
正好一个 行(如果可用) .如果多个产品并列最高销售额,我的任意(但确定性和可重复性)选择是具有较小 producto_id
.
的那个
如果您需要所有同龄人并列一天,请按照@Houari 的建议使用 rank()
。
SQLSELECT
查询中的事件序列在这个相关答案中有解释:
- Best way to get result count before LIMIT was applied
date_trunc()
只是 dia
计算中的噪音。我删除了它。
我将 NULLS LAST
添加到降序排序中,因为不清楚结果中是否存在 suma
为 NULL 的行:
- PostgreSQL sort by datetime asc, null first?
DISTINCT ON
和GROUP BY
中的数字只是为了方便起见的语法符号shorthand。类似:
- PostgreSQL equivalent for MySQL GROUP BY
与添加的 table 别名一样(语法 shorthand 符号)。
DISTINCT ON
的基础知识
- Select first row in each GROUP BY group?
我正在使用 PostgreSQL。 我需要select每个组的max,情况是table代表每天销售的产品,我想知道销量最高的每天的产品。
SELECT sum(detalle_orden.cantidad) as suma,detalle_orden.producto_id as producto
,to_char(date_trunc('day',orden.fecha AT TIME ZONE 'MST'),'DY') as dia
FROM detalle_orden
LEFT JOIN orden ON orden.id = detalle_orden.order_id
GROUP BY orden.fecha,detalle_orden.producto_id
ORDER BY dia,suma desc
正在返回:
suma producto dia
4 1 FRI
1 2 FRI
5 3 TUE
2 2 TUE
我想得到:
suma producto dia
4 1 FRI
5 3 TUE
只有每天的顶级产品(每个组的max(suma)
)。
我尝试了不同的方法,比如子查询,但是使用的聚合函数让事情变得有点困难。
您可以(滥用)使用带有适当排序子句的 SELECT DISTINCT ON
。假设您将之前的查询放入视图中:
SELECT DISTINCT ON (dia, producto) * FROM some_view ORDER BY dia, producto, suma DESC;
DISTINCT
确保您只会为每一天和产品保留一行,ORDER BY
确保它保留正确的一行
通过窗口函数:RANK 可以轻松搞定:
select * from
(
select suma,producto,dia, rank() over (partition by dia order by suma desc) as ranking
from your_query
)A
where ranking = 1
所以你最终的查询将是这样的:
select * from
(
select suma,producto,dia, rank() over (partition by dia order by suma desc) as ranking
from
(
SELECT sum(detalle_orden.cantidad) as suma,detalle_orden.producto_id as producto,to_char(date_trunc
('day',orden.fecha AT TIME ZONE 'MST'),'DY') as dia FROM detalle_orden LEFT JOIN
orden ON orden.id= detalle_orden.order_id GROUP by
orden.fecha,detalle_orden.producto_id ) B
) A
where ranking = 1
您仍然可以使用 DISTINCT ON
在没有子查询的单个查询级别中完成此操作,因为 DISTINCT
在 GROUP BY
和聚合函数之后(以及在 window 函数):
SELECT DISTINCT ON (3)
sum(d.cantidad) AS suma
, d.producto_id AS producto
, to_char(o.fecha AT TIME ZONE 'MST', 'DY') AS dia
FROM detalle_orden d
LEFT JOIN orden o ON o.id = d.order_id
GROUP BY o.fecha, d.producto_id
ORDER BY 3, 1 DESC NULLS LAST, d.producto_id;
备注
此解决方案 returns 每个
dia
正好一个 行(如果可用) .如果多个产品并列最高销售额,我的任意(但确定性和可重复性)选择是具有较小producto_id
.
的那个 如果您需要所有同龄人并列一天,请按照@Houari 的建议使用rank()
。SQL
SELECT
查询中的事件序列在这个相关答案中有解释:- Best way to get result count before LIMIT was applied
date_trunc()
只是dia
计算中的噪音。我删除了它。我将
NULLS LAST
添加到降序排序中,因为不清楚结果中是否存在suma
为 NULL 的行:- PostgreSQL sort by datetime asc, null first?
DISTINCT ON
和GROUP BY
中的数字只是为了方便起见的语法符号shorthand。类似:- PostgreSQL equivalent for MySQL GROUP BY
与添加的 table 别名一样(语法 shorthand 符号)。
的基础知识DISTINCT ON
- Select first row in each GROUP BY group?