1

我需要使用 t-sql 来查询两个表。第一个表是书籍。第二个表是作者。对于每个 Book 记录,可能有多个子 Author 记录。我想编写一个查询,它只返回为当前 Book 记录找到的第一个 Author 记录。表中有数十万条记录,因此我需要高效的查询。

select a.FirstName, a.LastName, b.BookName
from Books b
left join 
(
    select TOP 1 t.BookID, t.FirstName, t.LastName 
    from Authors t
) a 
    on a.BookID = b.BookID
where b.BookClassification = 2

这个查询是不对的。我只想选择与 BookID 匹配的 Authors 中的前 1 条记录。我怎样才能得到我正在寻找的结果?

4

3 回答 3

6

你很接近:

select a.FirstName, a.LastName, b.BookName
from Books b
outer apply 
(
    select TOP 1 t.BookID, t.FirstName, t.LastName 
    from Authors t
    WHERE t.BookID = b.BookID
    -- uncomment the next line to control which author to prefer
    -- ORDER BY t.<someColumn>...
) a 
where b.BookClassification = 2

虽然在我看来,Authors 会是 Books 的孩子,这似乎很奇怪...... :)

于 2012-04-10T18:21:12.623 回答
0

看看这是否更有效率。通过查找 min(authorID) 一次,您可能会获得更好的性能。

select author.FirstName, author.LastName, author.BookName    
from Books with (nolock) 
join 
(   select min(authorID) as authorID, bookID 
    from Authors with (nolock) 
    group by bookID 
)   as Author1
  on Author1.authorID = Books.authorID 
join Authors with (no lock) 
 on  Authors.authorID = Author1.authorID 
 and Authors.bookID = Author1.bookID
where Books.BookClassification = 2 
于 2012-04-10T18:43:34.787 回答
0

本着 TIMTOWDI 的精神。

您可以使用CTE,这是一个花哨的子查询,但如果子查询多次使用会很有帮助。还有一个等级函数,row_number()。

with bookAuthors as ( 
  select a.FirstName, a.LastName, b.BookName, BookClassification, 
    row_number() over(partition by b.BookName order by a.lastName ) as rank
  from Books b
  left join Authors a
    on a.BookID = b.BookID

)

select a.FirstName, a.LastName, b.BookName
from bookAuthors 
where rank = 1
  and BookClassification = 2 
于 2012-04-10T19:10:55.473 回答