我有一个相当复杂的查询,几乎模仿我在下面的测试查询:
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 JOIN
和Group G
上GroupDetail D
{并且根据表格WHERE
在C.code = 1
条件中没有INNER JOIN
}
我将LEFT OUTER JOIN
s替换为{{1}} s用于两个连接条件,但结果集不是预期的
如何有条件地执行JOIN
答案 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'))