Jon*_*ock 13 sql t-sql sql-server subquery
我一遍又一遍地使用相同的SQL模式,我知道必须有更好的方法,但我无法将它拼凑在一起.这是模式的一个简单版本,我将撤回学生的信息和他们签出的最后一本书(如果存在的话):
SELECT TStudents.*,
BookName = (SELECT TOP 1 BookName
FROM TBookCheckouts
WHERE StudentID = TStudents.ID
ORDER BY DateCheckedOut DESC),
BookAuthor = (SELECT TOP 1 BookAuthor
FROM TBookCheckouts
WHERE StudentID = TStudents.ID
ORDER BY DateCheckedOut DESC),
BookCheckout = (SELECT TOP 1 DateCheckedOut
FROM TBookCheckouts
WHERE StudentID = TStudents.ID
ORDER BY DateCheckedOut DESC)
FROM TStudents
Run Code Online (Sandbox Code Playgroud)
(为了这个例子,请忽略TBookCheckouts应该分成TCheckouts和TBooks的事实)
我想说明的是:我倾向于为同一个表中的列提供大量子查询.我也倾向于需要按日期对这些子查询表进行排序以获得最新记录,因此对于LEFT JOIN来说,这并不是那么简单(至少对我而言).但是请注意,除了返回哪个字段之外,我基本上做了3次相同的子查询.SQL Server可能足够聪明以优化它,但我不这么认为(我肯定需要在阅读执行计划方面做得更好......).
虽然以这种方式构造它可能是有利的(如果我有大量的子查询和子表,有时这最终会更具可读性),但这似乎并不是特别有效.
我已经考虑从派生表执行LEFT JOIN,可能包含ROW_NUMBER()和PARTITION BY,但我似乎无法将它们拼凑在一起.
Tho*_*mas 12
如果您使用的是SQL Server 2005及更高版本,则可以使用如下排名函数:
With LastCheckout As
(
Select StudentId, BookName, BookAuthor, DateCheckedOut
, Row_Number() Over ( Partition By StudentId Order By DateCheckedOut Desc) As CheckoutRank
From TBookCheckouts
)
Select ..., LastCheckout.BookName, LastCheckout.BookAuthor, LastCheckout.DateCheckedOut
From TStudents
Left Join LastCheckout
On LastCheckout.StudentId = TStudents.StudentId
And LastCheckout.CheckoutRank = 1
Run Code Online (Sandbox Code Playgroud)
在2005年及以后,OUTER APPLY是你的朋友:
SELECT TStudents.*,
t.BookName ,
t.BookAuthor ,
t.BookCheckout
FROM TStudents
OUTER APPLY(SELECT TOP 1 s.*
FROM TBookCheckouts AS s
WHERE s.StudentID = TStudents.ID
ORDER BY s.DateCheckedOut DESC) AS t
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
54980 次 |
| 最近记录: |