我有一种感觉,当我得到回答时,我会感到愚蠢。我有一张客户表和一张订单表。我想要一个查询,它给我一个所有客户的列表,以及它们的最后订单信息(如果有的话),按客户名称排序。
SELECT c.id, c.name, o.order_time, o.item_name
FROM clients AS c LEFT JOIN(
SELECT client_id, max(order_time) AS order_time
FROM orders GROUP BY client_id
) AS o
ON(c.id = o.client_id)
ORDER BY UPPER(c.name)"
我的问题是,如果删除o.item_name,我会得到我想要的行,但是所写的查询是无效的,因为如果没有将o.item_name放在GROUP BY中,就无法获取o.item_name。当然,这会导致它为每个客户端返回多行。希望我的意图很明确。
答案 0 :(得分:2)
您可以使用窗口功能执行此操作:
SELECT c.id, c.name, o.order_time, o.item_name
FROM clients AS c
LEFT JOIN (
SELECT client_id,
item_name,
order_time,
row_number() over (partition by client_id order by order_time desc) as rn
FROM orders
) AS o ON c.id = o.client_id and o.rn = 1
ORDER BY UPPER(c.name);
另一个选择是使用Postgres'distinct on()
运算符,它通常比使用窗口函数的解决方案更快:
SELECT c.id, c.name, o.order_time, o.item_name
FROM clients AS c
LEFT JOIN (
SELECT distinct on (client_id) client_id,
item_name,
order_time
FROM orders
order by client_id, order_time desc
) AS o ON c.id = o.client_id
ORDER BY UPPER(c.name);
答案 1 :(得分:0)
在Postgres中,您可以使用distinct on
:
SELECT DISTINCT ON (c.name) c.id, c.name, o.order_time, o.item_name
FROM clients c LEFT JOIN
orders o
ON c.id = o.client_id
ORDER BY UPPER(c.name), o.order_time DESC;