选择查询中带有子查询的IN子句

时间:2020-02-24 21:13:38

标签: sql sql-server

我有一个查询,我在其中联接多个表。我想根据状态代码过滤结果,我也想获取最近创建的记录。下面的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

1 个答案:

答案 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子句中的相关子查询/派生表,但是当您可能需要对同一个表使用多个子查询时,它可能会更快。这样一来,我们只需访问该表一次即可同时获得DetailStatusCodeCreateTimeStamp列。在Oracle和Postgresql中,这称为LATERAL JOIN。这些APPLY / Lateral连接操作与旧的过时的“ A,B”连接语法不能很好地融合在一起,而这只是许多不使用该旧语法的原因之一。

在行号等于1的情况下,通常还可以使用ROW_NUMBER()窗口函数来获得更好的性能。

请注意,Header表最初没有有意义的JOIN条件。明确的JOIN语法有助于使这种错误更加明显。我还必须从DetailStatus推断出您需要哪些字段。实际上,该表在原始查询中没有任何作用。

相关问题