举个例子,假设我有以下问题:
select
u.id,
u.name,
(select s.status from user_status s where s.user_id = u.id order by s.created_at desc limit 1) as status
from
user u
where
u.active = true;
以上查询效果很好。它返回所选用户的最新用户状态。但是,我想知道如何使用user_status
表上的连接获得相同的结果,而不是使用子查询。这样的事情可能吗?
我正在使用PostgreSQL。
感谢您提供任何帮助!
答案 0 :(得分:0)
select u.id , b.status
from user u join user_status b on u.id= b.user_id
where u.active = true;
order by b.s.created_at desc limit 1
我认为这项工作。 但在你的代码中有“b”,我不知道它是什么。
答案 1 :(得分:0)
JOIN
语法不直接提供订单或限制作为选项;所以严格来说,你不能直接实现你想要的加入。我认为解决问题的最简单方法是使用连接子查询,如下所示:
select
u.id
, u.name
, s.status
from user u
left join (
select
user_id
, status
, row_number() over(partition by user_id
order by created_at desc) as rn
from user_status s
) s on u.id = s.userid and s.rn = 1
where u.active = true;
此处,分析函数row_number()
与over()
子句相结合,使后续连接条件and s.rn=1
能够通过计算rn值来利用排序和限制连接行。
nb select子句中的相关子查询(在问题的查询中使用)就像左连接一样,因为它可以返回NULL。如果不需要或不需要该效果,您可以更改为内部联接。
可以将子查询移动到CTE中,但除非有令人信服的理由这样做,否则我更喜欢使用上面提到的更传统的形式。
另一种方法(Postgres 9.3或更高版本的 )是使用lateral
连接,它与原始子查询非常相似,但因为它成为from子句的一部分很可能在select子句中使用该子查询更有效率。
select
u.id
, u.name
, s.status
from user u
left join lateral (
select user_status.status
from user_status
where user_status.user_id = u.id
order by user_status.created_at desc
limit 1
) s ON true
where u.active = true;
答案 2 :(得分:0)
我最终做了以下工作,这对我很有帮助:
select
u.id,
u.name,
us.status
from
user u
left join (
select
distinct on (user_id)
*
from
user_status
order by
user_id,
created_at desc
) as us on u.id = vs.user_id
where
u.active = true;
这比我在问题中的查询更有效。
答案 3 :(得分:-1)
您可以通过将子查询转换为with子句并在连接中使用它来实现它