加入而不是相关子查询

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 优化——奇怪的执行计划左加入一个不相关的子查询

CakePHP 2.1 中的 Facebook 点赞对话列表(与分组最大值、子查询、加入相关)

oracle中的update语句能用相关子查询么?

MS Access 中的加入或子查询