连接中的相关子查询?

时间:2012-05-30 01:42:41

标签: sql sql-server-2008 subquery correlated-subquery

我有一个查询,我需要在连接中使用相关子查询。我说需要,我的意思是我认为我需要它......我怎么能这样做?我的查询如下,我得到“多部分标识符”FIELDNAME GOES HERE“无法绑定”错误...如何更改此查询才能生效?

SELECT FireEvent.ExerciseID, 
       FireEvent.FireEventID, 
       tempHitEvent.HitEventID, 
       FireEvent.AssociatedPlayerID, 
       tempHitEvent.AssociatedPlayerID, 
       FireEvent.EventTime, 
       tempHitEvent.EventTime, 
       FireEvent.Longitude, 
       FireEvent.Latitude, 
       tempHitEvent.Longitude, 
       tempHitEvent.Latitude, 
       tempHitEvent.HitResult, 
       FireEvent.AmmunitionCode, 
       FireEvent.AmmunitionSource, 
       FireEvent.FireEventID, 
       0 AS 'IsArtillery' 
FROM   FireEvent 
       LEFT JOIN (SELECT HitEvent.*, 
                         FireEvent.FireEventID, 
                         Rank() 
                           OVER ( 
                             ORDER BY HitEvent.EventTime) AS RankValue 
                  FROM   HitEvent 
                         WHERE FireEvent.EventTime BETWEEN 
                                    Dateadd(millisecond, -5000, 
                                    HitEvent.EventTime) AND 
                                               Dateadd(millisecond, 
                                               5000, HitEvent.EventTime) AND HitEvent.FiringPlayerID = FireEvent.PlayerID 
                   AND HitEvent.AmmunitionCode = 
                       FireEvent.AmmunitionCode
                   AND HitEvent.ExerciseID = 
                       'D289D508-1479-4C17-988C-5F6A847AE51E' 
                        AND FireEvent.ExerciseID = 
                       'D289D508-1479-4C17-988C-5F6A847AE51E' 
                   AND HitEvent.HitResult NOT IN ( 0, 1 ) ) AS 
                 tempHitEvent 
              ON ( 
              RankValue = 1
            AND tempHitEvent.FireEventID = 
                     FireEvent.FireEventID 
                     )
WHERE  FireEvent.ExerciseID = 'D289D508-1479-4C17-988C-5F6A847AE51E' 
ORDER BY HitEventID

3 个答案:

答案 0 :(得分:2)

使用OUTER APPLY代替LEFT JOIN。我不得不移动你的一些条款,但下面应该产生所需的结果

SELECT  FireEvent.ExerciseID, 
        FireEvent.FireEventID, 
        tempHitEvent.HitEventID, 
        FireEvent.AssociatedPlayerID, 
        tempHitEvent.AssociatedPlayerID, 
        FireEvent.EventTime, 
        tempHitEvent.EventTime, 
        FireEvent.Longitude, 
        FireEvent.Latitude, 
        tempHitEvent.Longitude, 
        tempHitEvent.Latitude, 
        tempHitEvent.HitResult, 
        FireEvent.AmmunitionCode, 
        FireEvent.AmmunitionSource, 
        FireEvent.FireEventID, 
        0 AS 'IsArtillery' 
FROM    FireEvent 
        OUTER APPLY
        (   SELECT  HitEvent.*, RANK() OVER (ORDER BY HitEvent.EventTime) AS RankValue 
            FROM    HitEvent 
            WHERE   HitEvent.FireEventID = FireEvent.FireEventID 
            AND     FireEvent.EventTime BETWEEN DATEADD(MILLISECOND, -5000, HitEvent.EventTime) AND DATEADD(MILLISECOND, 5000, HitEvent.EventTime) 
            AND     HitEvent.FiringPlayerID = FireEvent.PlayerID 
            AND     HitEvent.AmmunitionCode = FireEvent.AmmunitionCode
            AND     HitEvent.ExerciseID = FireEvent.ExerciseID
            AND     HitEvent.HitResult NOT IN ( 0, 1 ) 
        ) AS tempHitEvent 
WHERE   COALESCE(RankValue, 1) = 1
AND     FireEvent.ExerciseID = 'D289D508-1479-4C17-988C-5F6A847AE51E' 
ORDER BY FireEvent.HitEventID

如果您只想返回匹配HitEvent的结果,请使用CROSS APPLYCROSS APPLY OUTER APPLY INNER JOINLEFT JOIN的对象是OUTER APPLY


<强>附录

这可以通过不使用RANK的连接来实现,通过不使用子查询来连接HitEvent,然后对所有数据执行RANK函数,而不仅仅是HitEvent表。这一切都需要移动到子查询,因此WHERE函数的结果可以包含在SELECT * FROM ( SELECT FireEvent.ExerciseID, FireEvent.FireEventID, HitEvent.HitEventID, FireEvent.AssociatedPlayerID, --HitEvent.AssociatedPlayerID, FireEvent.EventTime, HitEvent.EventTime [HitEventTime], FireEvent.Longitude [FireEventLongitute], FireEvent.Latitude [FireEventLatitute], HitEvent.Longitude [HitEventLongitute], HitEvent.Latitude [HitEventLatitute], HitEvent.HitResult , FireEvent.AmmunitionCode, FireEvent.AmmunitionSource, 0 [IsArtillery], RANK() OVER(PARTITION BY HitEvent.FireEventID, HitEvent.FiringPlayerID, HitEvent.AmmunitionCode,HitEvent.ExerciseID ORDER BY HitEvent.EventTime) [RankValue] FROM FireEvent LEFT JOIN HitEvent ON HitEvent.FireEventID = FireEvent.FireEventID AND FireEvent.EventTime BETWEEN DATEADD(MILLISECOND, -5000, HitEvent.EventTime) AND DATEADD(MILLISECOND, 5000, HitEvent.EventTime) AND HitEvent.FiringPlayerID = FireEvent.PlayerID AND HitEvent.AmmunitionCode = FireEvent.AmmunitionCode AND HitEvent.ExerciseID = FireEvent.ExerciseID AND HitEvent.HitResult NOT IN ( 0, 1 ) ) data WHERE RanKValue = 1 子句中。

OUTER APPLY

与使用{{1}}相比,这可能会略微提高性能,但可能不会。这取决于您的架构和您正在处理的数据量。测试无可替代:

答案 1 :(得分:0)

Cross Apply适用于此场景......

SELECT FireEvent.ExerciseID, 
       FireEvent.FireEventID, 
       tempHitEvent.HitEventID, 
       FireEvent.AssociatedPlayerID, 
       tempHitEvent.AssociatedPlayerID, 
       FireEvent.EventTime, 
       tempHitEvent.EventTime, 
       FireEvent.Longitude, 
       FireEvent.Latitude, 
       tempHitEvent.Longitude, 
       tempHitEvent.Latitude, 
       tempHitEvent.HitResult, 
       FireEvent.AmmunitionCode, 
       FireEvent.AmmunitionSource, 
       FireEvent.FireEventID, 
       0 AS 'IsArtillery' 
       ,RankValue
FROM   FireEvent
       CROSS APPLY  (SELECT HitEvent.*, 
                         FireEvent.FireEventID, 
                         Rank() 
                           OVER ( 
                             ORDER BY HitEvent.EventTime) AS RankValue 
                  FROM   HitEvent 
                         WHERE FireEvent.EventTime BETWEEN 
                                    Dateadd(millisecond, -5000, 
                                    HitEvent.EventTime) AND 
                                               Dateadd(millisecond, 
                                               5000, HitEvent.EventTime) AND HitEvent.FiringPlayerID = FireEvent.PlayerID 
                   AND HitEvent.AmmunitionCode = 
                       FireEvent.AmmunitionCode
                   AND HitEvent.ExerciseID = 
                       'D289D508-1479-4C17-988C-5F6A847AE51E' 
                        AND FireEvent.ExerciseID = 
                       'D289D508-1479-4C17-988C-5F6A847AE51E' 
                   AND HitEvent.HitResult NOT IN ( 0, 1 ) )  
                 tempHitEvent 
              WHERE 
              RankValue = 1
            AND tempHitEvent.FireEventID = 
                     FireEvent.FireEventID 

AND  FireEvent.ExerciseID = 'D289D508-1479-4C17-988C-5F6A847AE51E' 
ORDER BY HitEventID

答案 2 :(得分:0)

您不需要相关子查询。你似乎有一个相对简单的联接,虽然同时在几个领域。

以下FROM子句从子查询内部提取引用两个表的条​​件,并将它们移到JOIN子句外部。这接近你想要的,取决于排名中的分区是否正在按预期执行:

FROM FireEvent fe left outer join
     (SELECT HitEvent.*, 
             Rank() OVER (partition by FiringPlayerID, ExerciseID, FireEventID, FireEventID
                          ORDER BY HitEvent.EventTime) AS RankValue 
      FROM HitEvent 
      WHERE HitEvent.ExerciseID = 'D289D508-1479-4C17-988C-5F6A847AE51E' AND  
            HitEvent.HitResult NOT IN ( 0, 1 )
     ) he
     ON he.FiringPlayerID  = fe.PlayerId and
        he.AmmunitionCode = fe.AmmunitionCode and
        fe.EventTime BETWEEN Dateadd(millisecond, -5000, he.EventTime) AND 
                             Dateadd(millisecond, 5000, he.EventTime) AND
        fe.ExerciseID = 'D289D508-1479-4C17-988C-5F6A847AE51E' AND
        RankValue = 1 , d
        he.FireEventID =  fe.FireEventID