我有这些表
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个子查询,我感觉它没有被优化,并且如果与等效的内部连接一起使用它可以表现得更好。那么,什么是相同的内部联接呢?我正在做的是找到添加到库中的第一个给定作者。
答案 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;