我的表客户端有这样的列:
ClientId LastChanged
671154 2012-07-21 14:35:40.780
671154 2012-07-21 14:35:41.630
671155 2012-07-21 14:37:24.213
我也有表ClientsHistory,其列如下:
ClientId Changed Name StateCode
671154 2012-07-21 14:35:40.780 91C6672EB2D4496AB34D3C 22654624
671154 2012-07-21 14:35:41.630 55E345FE6A144B0E92A6026D8B461CEA 22654624
671154 2013-03-13 12:56:33.943 D32841A8EBAB44999C966D2F597DC240 22654624
我想在LastChanged日期之后在ClientsHistory中查询客户端和仅第一行:
SELECT ( SELECT TOP 1
Name
FROM dbo.ClientsHistory
WHERE ClientId = c.ClientId
AND Changed > c.LastChanged
ORDER BY [Changed] ASC
) ,
( SELECT TOP 1
StateCode
FROM dbo.СlientsHistory
WHERE ClientId = c.ClientId
AND Changed > c.LastChanged
ORDER BY [Changed] ASC
) ,
c.ClientId,
c.LastChanged
FROM Clients c
如何重写此查询以消除ClientsHistory表中每个字段的子查询?
先谢谢。
答案 0 :(得分:1)
您可以使用CTE,排名函数ROW_NUMBER
和LEFT JOIN
:
WITH Hist AS
(
SELECT c.ClientId, Changed, Name, StateCode, c.LastChanged,
RN = ROW_NUMBER() OVER (PARTITION BY c.ClientId
ORDER BY Changed DESC)
FROM dbo.Clients c INNER JOIN dbo.ClientsHistory ch
ON c.ClientId = ch.ClientId
WHERE c.LastChanged > ch.Changed
)
SELECT c.ClientId, c.LastChanged, h.Changed, Name, StateCode
FROM dbo.Clients c LEFT JOIN Hist h
ON c.ClientId = h.ClientId
AND c.LastChanged = h.LastChanged -- necessary since ClientId is not unique in hist
AND h.RN = 1
答案 1 :(得分:1)
为了消除每个列的单独子查询的需要,您可以像这样使用APPLY:
SELECT ch.Name,
ch.StateCode,
c.ClientId,
c.LastChanged
FROM dbo.Clients c
OUTER APPLY (SELECT TOP 1 *
FROM dbo.ClientsHistory
WHERE ClientId = c.ClientId
AND Changed > c.LastChanged
ORDER BY Changed ASC) ch
此处,将为客户端中的每一行执行子查询。
答案 2 :(得分:0)
此查询必须返回相同的结果。你能测试一下:
SELECT temp.Name,
temp.StateCode,
c.ClientId,
c.LastChanged
FROM Clients c
INNER JOIN
(SELECT TOP 1 c2.ClientId
c2.Name,
c2.StateCode
FROM Clients c2
INNER JOIN dbo.ClientsHistory ch
ON ch.ClientId = c2.ClientId
AND ch.Changed > c2.LastChanged
ORDER BY [Changed] ASC) temp
ON temp.ClientId = c.ClientId