TSQL 左连接,只有右起最后一行
Posted
技术标签:
【中文标题】TSQL 左连接,只有右起最后一行【英文标题】:TSQL left join and only last row from right 【发布时间】:2011-01-17 21:38:38 【问题描述】:我正在编写 sql 查询来获取帖子,并且只有该帖子的最后一条评论(如果存在)。 但我无法找到一种方法来限制左连接中右列仅 1 行。
这是此查询的示例。
SELECT post.id, post.title,comment.id,comment.message
from post
left outer join comment
on post.id=comment.post_id
如果帖子有 3 个 cmets,我会得到 3 行这个帖子,但我只想要 1 行最后评论(按日期排序)。
有人可以帮我解决这个问题吗?
【问题讨论】:
【参考方案1】:SELECT post.id, post.title, comment.id, comment.message
FROM post
OUTER APPLY
(
SELECT TOP 1 *
FROM comment с
WHERE c.post_id = post.id
ORDER BY
date DESC
) comment
或
SELECT *
FROM (
SELECT post.id, post.title, comment.id, comment.message,
ROW_NUMBER() OVER (PARTITION BY post.id ORDER BY comment.date DESC) AS rn
FROM post
LEFT JOIN
comment
ON comment.post_id = post.id
) q
WHERE rn = 1
前者对于每个帖子中有很多 cmets 的帖子效率更高;后者对于许多帖子中只有很少的 cmets 更有效。
【讨论】:
感谢您的回答。我使用下一个代码。 SELECT post.id, post.title,c.id as comment_id,c.message from post left outer join (select comment.id,comment.post_id,comment.message, ROW_NUMBER() OVER (PARTITION BY comment.post_id ORDER BY comment .date DESC) AS rn from comment) c on post.id=c.post_id where c.rn=1 or c.rn is null APPLY 运算符为我解决了这个问题。我正在进行一对多连接,但需要将右侧匹配减少到仅最近创建的匹配。谢谢! 将这两个放在一起显示估计的查询计划很有趣,apply
选项是查询成本的 99% :o
@FelipeSabino:如果您在大象笼子上看到“水牛”标志,请不要相信自己的眼睛。【参考方案2】:
子查询:
SELECT p.id, p.title, c.id, c.message
FROM post p
LEFT join comment c
ON c.post_id = p.id AND c.id =
(SELECT MAX(c.id) FROM comment c2 WHERE c2.post_id = p.id)
【讨论】:
如果我没有遗漏什么,这应该比我的执行计划所接受的答案快得多(比如 10 倍)。 对我来说,这似乎比在接受的答案中使用庞大的子查询更有效。 ***.com/questions/4692419/… 中有相关的答案。它在子查询中使用 TOP 1/ORDER BY 解决方案而不是 MAX。 我相信这是更简短更好的答案。 这将在按 ID 排序时返回最后一条评论,而不是按 OP 要求的日期排序【参考方案3】:您需要加入一个返回帖子最后评论的子查询。例如:
select post.id, post.title. lastpostid, lastcommentmessage
from post
inner join
(
select post.id as lastpostid, max(comment.id) as lastcommentmessage
from post
inner join comment on commment.post_id = post.id
group by post.id
) lastcomment
on lastpostid = post.id
【讨论】:
【参考方案4】:几个选项....
一种方法是在以下位置进行 JOIN:
SELECT TOP 1 comment.message FROM comment ORDER BY comment.id DESC
(注意我假设 comment.id 是一个身份字段)
【讨论】:
如果Identity字段有负增量怎么办? 你遇到过这样的事情吗?【参考方案5】:什么版本的 SQL Server?如果您有可用的 Row_Number() 函数,您可以按照“first”对您的任何含义对 cmets 进行排序,然后添加“where RN=1”子句。在我的脑海中没有一个方便的示例或正确的语法,但确实有大量的查询可以做到这一点。其他帖子都是你可以做到这一点的 1000 种方式。
我会说它,看看哪一个最适合你。
【讨论】:
【参考方案6】:你没有说你的日期字段的具体名称,所以我填写了[DateCreated]
。这与上面 AGoodDisplayName 的帖子基本相同,但使用日期字段而不是依赖 ID 列排序。
SELECT post.id, post.title, comment.id, comment.message
FROM post p
LEFT OUTER JOIN comment
ON comment.id = (
SELECT TOP 1 id
FROM comment
WHERE p.id = post_id
ORDER BY [DateCreated] ASC
)
【讨论】:
以上是关于TSQL 左连接,只有右起最后一行的主要内容,如果未能解决你的问题,请参考以下文章