我有一个查询,我在其中联接多个表。我想根据状态代码过滤结果,我也想获取最近创建的记录。下面的SQL正确吗?含义-我可以对状态码使用IN子句,还是应该使用三个不同的查询,每个状态一个?
SELECT
A.DetailID
, H.PersonID
, A.RateAmount
, A.Code
, A.TypeCode
FROM
CMPN.Detail A
, CMPN.DetailStatus B
, CMPN.Header H
WHERE
H.PayGroup IN ('A Pay Group','B Pay Group','C Pay Group')
AND A.EndDate = '2020-02-10 06:00:00.0000000 +00:00'
AND A.LastUpdateTimestamp <= '2020-02-24 06:00:00.0000000 +00:00'
AND A.DetailID = B.DetailID
AND H.HeaderId = A.HeaderId
AND **B.DetailStatusCode IN ('Approved','Completed','Pending')**
AND B.CreateTimestamp =
(
SELECT
MAX(C.CreateTimestamp)
FROM
CMPN.DetailStatus C
WHERE
A.DetailID = C.DetailID AND **C.DetailStatusCode IN ('Approved','Completed','Pending'**)
)
ORDER BY
H.PersonID
, A.Code
, A.TypeCode
答案 0 :(得分:2)
目前尚不清楚您要做什么(请参阅我对这个问题的评论)。但我最大的猜测是您可以使用APPLY
来做到这一点:
SELECT d.DetailID, h.PersonID, d.RateAmount, d.Code, d.TypeCode
, s.DetailStatusCode AS [Status], s.CreateTimeStamp As [StatusDate]
FROM CMPN.Detail d
CROSS APPLY ( -- change this to OUTER APPLY if you need it to behave more like a LEFT JOIN
SELECT TOP 1 DetailSatusCode, CreateTimeStamp
FROM CMPN.DetailStatus ds
WHERE ds.DetailID = d.DetailID
AND ds.DetailStatusCode IN ('Approved','Completed','Pending')
ORDER BY ds.CreateTimeStamp DESC
) s
INNER JOIN CMPN.Header h ON h.HeaderID = d.HeaderID
AND h.PayGroup IN ('A Pay Group','B Pay Group','C Pay Group')
WHERE d.EndDate = '2020-02-10 06:00:00.0000000 +00:00'
AND d.LastUpdateTimestamp <= '2020-02-24 06:00:00.0000000 +00:00'
ORDER BY h.PersonID, d.Code, d.TypeCode
APPLY
类似于SELECT
子句中的相关子查询/派生表,但是当您可能需要对同一个表使用多个子查询时,它可能会更快。这样一来,我们只需访问该表一次即可同时获得DetailStatusCode
和CreateTimeStamp
列。在Oracle和Postgresql中,这称为LATERAL JOIN
。这些APPLY / Lateral连接操作与旧的过时的“ A,B”连接语法不能很好地融合在一起,而这只是许多不使用该旧语法的原因之一。
在行号等于1的情况下,通常还可以使用ROW_NUMBER()
窗口函数来获得更好的性能。
请注意,Header
表最初没有有意义的JOIN条件。明确的JOIN
语法有助于使这种错误更加明显。我还必须从DetailStatus
推断出您需要哪些字段。实际上,该表在原始查询中没有任何作用。