postgresql 如何限制左连接的结果并将其用于下一个左连接?

ykejflvf  于 2022-12-23  发布在  PostgreSQL
关注(0)|答案(3)|浏览(175)

我的查询涉及三个实体,所以我有两个左连接。我想限制第一个连接的结果。例如,我们有客户和订单评估。在第一个连接中,我只想得到挂在客户上的最新订单评估。较早的订单评估不感兴趣。在此之后,我连接另一个表(依赖于客户和订单重估)并要求某些条件。我似乎找不到如何在createstamp的帮助下限制第一个连接结果。
我的查询草稿如下所示:

SELECT * FROM customer 
left join (SELECT * FROM orderevaluation ORDER BY createstamp desc LIMIT 1) o on customer.id = o.customer_id
left join ... WHERE ... AND ... ;

这里的问题是,只有一个orderevaluation选择我的所有订单,而不是每个订单一个.我想选择最年轻的orderevaluation每个客户,然后再次加入.
我也试过:

customer.id =

但是在那里我只能使用id,而不能使用createstamp
WHERE条件之后,我尝试使用ORDER BY o.createstamp DESC limit 1,但它也不起作用。

xfyts7mz

xfyts7mz1#

通常,您为一个或几个选定客户(在未公开的外部WHERE子句中筛选)运行这样的查询。然后,LATERAL子查询通常速度最快,因为它只处理感兴趣的几个客户,而不是整个表。

SELECT ...
FROM   customer c
LEFT   JOIN LATERAL (
   SELECT o.*
   FROM   orderevaluation o
   WHERE  o.customer_id = c.id
   ORDER  BY o.customer_id, o.createstamp DESC NULLS LAST
   LIMIT  1
   ) o ON true
LEFT  JOIN ... 
WHERE ...  -- filtering *few* customers

参见:

  • 单个查询中的多个array_agg()调用

关于LATERAL连接:

  • 在PostgreSQL中,横向连接和子查询有什么区别?

确保有一个以customer_id开头的索引,最好是在orderevaluation(customer_id, customer_id, createstamp DESC NULLS LAST)上。
如果列定义为NOT NULL,则从索引和查询中删除NULLS LAST
对于其他联接,请考虑:

  • 两个SQL左连接生成不正确的结果
jchrr9hc

jchrr9hc2#

我想选择每个客户最年轻的订单重估,然后再次加入。
您通常会过滤子查询中的第一个表。在Postgres中,一种方法使用distinct on。从您的伪代码开始:

SELECT ...  -- enumerate wanted cols here 
FROM customer c
LEFT JOIN (
    SELECT DISTINCT ON (customer_id) o.*
    FROM orderevaluation o
    ORDER BY customer_id, createstamp DESC
) o on customer.id = o.customer_id
LEFR JOIN ... 
WHERE ...

另一种方法是使用横向连接而不是左连接(然后我们确实可以使用limit,正如您尝试的那样)-这将需要更多关于表设计的上下文。

a9wyjsp7

a9wyjsp73#

要选择每个客户的最新订单评估,可以在第一个LEFT JOIN的ON子句中使用子查询来获取每个客户的最新订单评估。以下是如何执行此操作的示例:

SELECT *
FROM customer c
LEFT JOIN orderevaluation o ON o.customer_id = c.id AND o.createstamp = (SELECT MAX(createstamp) FROM orderevaluation WHERE customer_id = c.id)
LEFT JOIN ...
WHERE ... AND ...

这将为每个客户选择最新的订单评估,并使用LEFT JOIN将其连接到customer表。然后,您可以使用ordererevaluation表中的createstamp列,根据需要在WHERE子句中过滤结果。希望我能帮上忙。

相关问题