内连接等效于此子查询?

时间:2012-09-26 03:02:05

标签: sql-server join subquery

我有这些表

BooksCatalog
[BookCatalogID],[BooksCatalogBookID],[ReceivedFrom],[BillNo],[billdate]

Books
[BookID],[BookTitle],[ISBN],[ISBN13],[BookAuthorID],[BookPublisherID],[YearPublished],[NumberOfPages],[Volume],[edition],[Price]

Authors
[AuthorID],[AuthorName],[AuthorCityID],[AuthorStateID],[PhoneNumber],[Email],[Website]

我正在运行此查询,

SELECT Books.BookTitle FROM Books 
        INNER JOIN Authors ON Authors.AuthorId=Books.BookAuthorID
        WHERE Books.BookID IN 
        (SELECT BooksCatalog.BooksCatalogBookID FROM BooksCatalog
        WHERE BooksCatalog.billdate = (SELECT MIN(BooksCatalog.billdate) FROM BooksCatalog))
        AND
        AUTHORS.AuthorName = @AuthorName;

因为它使用了2个子查询,我感觉它没有被优化,并且如果与等效的内部连接一起使用它可以表现得更好。那么,什么是相同的内部联接呢?我正在做的是找到添加到库中的第一个给定作者。

2 个答案:

答案 0 :(得分:2)

在整个架构中使用别名,模式前缀和命名元素(例如BookId或AuthorId)时,有很多东西要说。它真的需要被称为BookAuthorId或BooksCatalogBookID吗?

无论如何,您的查询可以通过这种方式重新编写,但正如@billy建议的那样,它可能不会真正受益于一个截然不同的计划:

SELECT b.BookTitle 
FROM dbo.Books AS b 
INNER JOIN Authors AS a 
ON a.AuthorId = b.BookAuthorID
INNER JOIN 
(
  SELECT BookId = MIN(BooksCatalogBookID)
   FROM dbo.BooksCatalog 
) AS bc
ON bc.BookId = b.BookId
WHERE a.AuthorName = @AuthorName;

虽然你在这里依赖于非常奇特的连接标准。目录中所有书籍的概率是多少,最早的法案日期也可能是由您确定的一位作者撰写的?您的逻辑真的可能是从指定的作者那里获得第一本收费书吗?如果是这样,那么这可能更有意义:

;WITH x(BookTitle, rn) AS
(
  SELECT b.BookTitle, ROW_NUMBER() OVER (ORDER BY bc.billdate)
    FROM dbo.BooksCatalog AS bc
    INNER JOIN b.Books AS b
    ON b.BookId = bc.BooksCatalogBookID
    INNER JOIN dbo.Authors AS a
    ON b.BookAuthorID = a.AuthorID
    WHERE a.AuthorName = @AuthorName
)
SELECT BookTitle FROM x WHERE rn = 1; 

答案 1 :(得分:0)

您可以使用内部联接替换一个子查询。

            SELECT Books.BookTitle 
              FROM Books 
        INNER JOIN Authors 
                ON Authors.AuthorId = Books.BookAuthorID
        INNER JOIN BooksCatalog 
                ON BooksCatalog.BooksCatalogBookID = Books.BookID 
               AND BooksCatalog.billdate = (SELECT MIN(BooksCatalog.billdate) FROM BooksCatalog) WHERE BooksCatalogBookID = Books.BookID)
        WHERE      Authors.AuthorName = @AuthorName;