如何在我的Join中使用Union或Intersect而不是OR

时间:2013-05-13 23:19:59

标签: sql sql-server sql-server-2008

以下查询有效,但从我的阅读开始,OR中的JOIN并不是获得结果的最有效方法。我想也许我应该使用UNIONINTERSECT,但我无法弄清楚如何实现这一目标。有人可以解释“正确”的结果吗?

WITH CTE1 AS (SELECT SC, SN, COUNT(AL) AS UNEXCUSED 
              FROM ATT 
              WHERE AL = 'U' 
              GROUP BY SC, SN),
     CTE2 AS (SELECT SC, SN, COUNT(AL) AS SUSPENDED 
              FROM ATT 
              WHERE AL = 'S' 
              GROUP BY SC, SN) 
SELECT STU.ID, STU.SC, STU.SN, 
       ISNULL(CTE1.UNEXCUSED, '') AS UNX,
       ISNULL(CTE2.SUSPENDED, '') AS SUS 
FROM CTE2
FULL JOIN CTE1 
       ON CTE1.SC = CTE2.SC 
          AND CTE1.SN = CTE2.SN
JOIN STU 
  ON (CTE1.SC = STU.SC 
      AND CTE1.SN = STU.SN) 
     OR (CTE2.SC = STU.SC 
         AND CTE2.SN = STU.SN)
WHERE STU.SC IN (1,2,4,9,11,15)

这是输出的示例:

ID      SC  SN     UNX  SUS
4291432 15  602    0    8
4296250 15  688    6    3
4216462 15  695    0    12
4916602 15  623    0    2
4295193 1   150    1    0
4215874 2   216    1    0
4005707 15  297    1    0

谢谢。

1 个答案:

答案 0 :(得分:0)

就个人而言,我会改变您的查询:

WITH CTE1 AS (SELECT SC, SN, COUNT(AL) AS UNEXCUSED 
              FROM ATT 
              WHERE AL = 'U' 
              GROUP BY SC, SN),
     CTE2 AS (SELECT SC, SN, COUNT(AL) AS SUSPENDED 
              FROM ATT 
              WHERE AL = 'S' 
              GROUP BY SC, SN) 
SELECT STU.ID, STU.SC, STU.SN, 
       ISNULL(CTE1.UNEXCUSED, '') AS UNX,
       ISNULL(CTE2.SUSPENDED, '') AS SUS 
FROM STU
LEFT JOIN CTE1
       ON (CTE1.SC = STU.SC 
           AND CTE1.SN = STU.SN) 
LEFT JOIN CTE2 
       ON (CTE2.SC = STU.SC 
           AND CTE2.SN = STU.SN)
WHERE STU.SC IN (1,2,4,9,11,15)

....如果没有其他原因,它会使您的预期结果更加清晰。请注意,优化器可能仍会生成相同的解释计划。