加入而不是相关子查询
Posted
技术标签:
【中文标题】加入而不是相关子查询【英文标题】:Join instead of correlated subquery 【发布时间】:2009-10-21 14:40:49 【问题描述】:CREATE TABLE BlogPosts
(
PostID INT PRIMARY KEY not null,
PostTitle NVARCHAR ,
BlogID int,
TotalComments int
)
是否可以使用任何 Join 而不是相关子查询来简化此查询?
SELECT TOP 5 *
FROM BlogPosts as t0
WHERE t0.PostID = (SELECT TOP 1 t1.PostID
FROM BlogPosts as t1
WHERE t0.BlogID = t1.BlogID
ORDER BY t1.TotalComments DESC)
我需要来自不同博客的 5 篇帖子,总评论数最多。
UPD。 SQL Server,但我更喜欢标准 SQL
【问题讨论】:
您声明的 sql 未排序,因此不能保证其中的前 5 行返回任何特定的五行...可能有更多 thabn 5 行满足 Where 子句...当您已经写了,你可能会从同一个博客中获得所有五个,或者混合。你想要哪一个? 不,我总是需要来自不同博客的评论最多的帖子,而不是来自同一个博客,否则会更容易:) 【参考方案1】:如果我理解正确,postid 是唯一的,所以这应该会有所帮助
编辑:
好的,那就试试这个
DECLARE @BlogPosts TABLE
(
PostID INT PRIMARY KEY not null,
PostTitle NVARCHAR ,
BlogID int,
TotalComments int
)
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 1, 'A', 1, 3
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 2, 'B', 1, 4
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 3, 'C', 2, 5
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 4, 'D', 2, 6
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 5, 'E', 2, 7
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 6, 'F', 1, 8
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 7, 'G', 3, 9
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 8, 'H', 4, 10
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 9, 'I', 5, 11
INSERT INTO @BlogPosts (PostID,PostTitle,BlogID,TotalComments) SELECT 10, 'J', 6, 5
SELECT TOP 5 *
FROM @BlogPosts bp INNER JOIN
(
SELECT BlogID,
MAX(TotalComments) MaxComments
FROM @BlogPosts
GROUP BY BlogID
) maxCommentsPerBlog ON bp.BlogID = maxCommentsPerBlog.BlogID
AND bp.TotalComments = maxCommentsPerBlog.MaxComments
ORDER BY bp.TotalComments DESC
不过,您可能有多个最大 blog-totalComments 组合。
【讨论】:
@astander:为什么是“@BlogPosts”而不是“BlogPosts”?这不是临时表。 这是我在 TSQL 中的测试表【参考方案2】:这将为您提供每个博客的热门帖子:
SELECT * FROM (
SELECT *, Ranking = ROW_NUMBER() OVER (PARTITION BY BlogID ORDER BY TotalComments DESC)
FROM BlogPosts
) a
WHERE Ranking = 1
或者:
SELECT b.*
FROM (
SELECT DISTINCT BlogID
FROM BlogPosts
) a
CROSS APPLY (
SELECT TOP 1 b.* FROM BlogPosts b
WHERE a.BlogID = b.BlogID
ORDER BY b.TotalComments DESC
) b
这就是你要找的吗?
【讨论】:
Partition 很好,谢谢,可能比加入更好。【参考方案3】:为什么需要连接和子查询? 为什么不能写
SELECT TOP 5 *
FROM @BlogPosts bp order by TotalComments desc;
【讨论】:
可能是因为@rudnev 需要“来自不同博客”的前 5 名。您的查询可能会返回,例如仅来自一个博客的前 5 名。以上是关于加入而不是相关子查询的主要内容,如果未能解决你的问题,请参考以下文章
Oracle 优化——奇怪的执行计划左加入一个不相关的子查询