SQL Server中的条件INNER JOIN

时间:2012-02-06 22:12:21

标签: sql sql-server-2008

我有一个相当复杂的查询,几乎模仿我在下面的测试查询:

SELECT C.*
  FROM Customer C 
       INNER JOIN CustDetail CD ON C.CustomerId = CD.CustomerId
       INNER JOIN Address A ON CD.DetailID = A.DetailID
       INNER JOIN Group G ON C.CustomerId = G.CustomerId   --Join only when C.code = 1
       INNER JOIN GroupDetail D ON G.GroupId = D.DetailId  --Join only when C.code = 1
WHERE G.Active = 1 AND        --Only when C.code = 1
      D.code = '1' AND        --Only when C.code = 1
      C.Id = @customerId

我想在INNER JOINGroup GGroupDetail D {并且根据表格WHEREC.code = 1条件中没有INNER JOIN }

我将LEFT OUTER JOIN s替换为{{1}} s用于两个连接条件,但结果集不是预期的

如何有条件地执行JOIN

3 个答案:

答案 0 :(得分:4)

SELECT C.*
  FROM Customer C 
       INNER JOIN CustDetail CD ON C.CustomerId = CD.CustomerId
       INNER JOIN Address A ON CD.DetailID = A.DetailID
       LEFT OUTER JOIN Group G ON C.CustomerId = G.CustomerId
       LEFT OUTER JOIN GroupDetail D ON G.GroupId = D.DetailId
WHERE ((G.Active = 1 AND C.code = 1) OR G.Active IS NULL) AND
      ((D.code = '1' AND C.code = 1) OR D.code IS NULL) AND
      C.Id = @customerId

我猜你之前没有包含IS NULL检查所以你永远不会看到C.code<>的行1?

您应该在永远不为null的字段上检查NULL。这几乎总是'id',但是你不清楚你有G.id还是D.id。

答案 1 :(得分:0)

仅当代码为1时才会进行半连接。

SELECT C.*
FROM Customer C 
    INNER JOIN CustDetail CD 
        ON C.CustomerId = CD.CustomerId
    INNER JOIN Address A 
        ON CD.DetailID = A.DetailID
WHERE 
      C.Id = @customerId AND
      (c.code != 1 OR
      EXISTS(
         SELECT NULL
         FROM Group G
            JOIN GroupDetail D ON G.GroupId = D.DetailId
         WHERE
            C.CustomerId = G.CustomerId AND
            G.Active = 1 AND 
            D.code = '1'
      ))

答案 2 :(得分:0)

我猜你想要的只是一个更严格的ON条款和一个复合条件。

SELECT C.*
  FROM Customer C 
       INNER JOIN CustDetail CD ON C.CustomerId = CD.CustomerId
       INNER JOIN Address A ON CD.DetailID = A.DetailID
       -- the next two joins happen only when c.code=1
       -- their columns will be null when there is no match.
       LEFT JOIN Group G ON C.CustomerId = G.CustomerId AND C.Code = 1
       LEFT JOIN GroupDetail D ON G.GroupId = D.DetailId AND C.Code = 1
WHERE C.Id = @customerId AND --always check this
      -- this condition is true if code is null or code isn't 1,
      ((C.code IS NULL or C.code <> 1)
      -- or (if the code is 1), it is true if g.active and d.code
       OR (G.Active = 1 AND D.code = '1'))