简化 LEFT JOIN
Simplifying LEFT JOINs
所以我有这个查询:
SELECT c1.field1, c2.field2
FROM table1 c1
LEFT JOIN table1 c2 ON c1.field1 = c2.field1 AND c1.field2 = :arg1 AND c2.field2 <> :arg1
LEFT JOIN table2 cc ON c2.field2 = cc.field2 AND cc.field3 = :arg2
WHERE (c2.field2 IS NULL OR cc.field2 IS NOT NULL)
ORDER BY ISNULL(c2.field2) ASC
这有两件事:
- 为给定的
field2
值选择 table1.field1
。
- 从第二个 table 中选取一个
table1.field2
,其中 field1 与前一点相同,也有一个特定的 属性。 (因为归一化才这么复杂)如果这不存在那么 return NULL
.
虽然这行得通,但它真的很难看。有没有更简单的版本做同样的事情?我最烦恼的是第二个 JOIN
需要是一个 LEFT
,然后是这个 WHERE
。我觉得 INNER
应该更简单,但它不起作用。
尝试将左连接转移到union
和inner join
,然后你可以得到一个新的查询:
SELECT c1.field1, null as field2
FROM table1 c1
UNION ALL
SELECT c1.field1, c2.field2
FROM table1 c1
INNER JOIN table1 c2 ON c1.field1 = c2.field1
INNER JOIN table2 cc ON c2.field2 = cc.field2
WHERE c1.field2 = :arg1 AND c2.field2 <> :arg1 AND cc.field3 = :arg2
首先,我通过拆分 where 子句将您的原始查询从 join
转移到 union
:
SELECT c1.field1, c2.field2
FROM table1 c1
LEFT JOIN table1 c2 ON c1.field1 = c2.field1 AND c1.field2 = :arg1 AND c2.field2 <> :arg1
WHERE (c2.field2 IS NULL )
UNION ALL
SELECT c1.field1, c2.field2
FROM table1 c1
INNER JOIN table1 c2 ON c1.field1 = c2.field1 AND c1.field2 = :arg1 AND c2.field2 <> :arg1
LEFT JOIN table2 cc ON c2.field2 = cc.field2 AND cc.field3 = :arg2
WHERE (c2.field2 IS NOT NULL AND cc.field2 IS NOT NULL)
但是 union 的第一部分可以像这样保持传输:
SELECT c1.field1, null
FROM table1 c1
WHERE c1.field2 <> :arg1 --c2.field2 must be null
UNION ALL
SELECT c1.field1, c2.field2
FROM table1 c1
LEFT JOIN table1 c2 ON c1.field1 = c2.field1 AND c2.field2 <> :arg1
WHERE c1.field2 = :arg1 AND c2.field2 IS NULL
最后,我得到了将所有左连接转移到联合和内连接的顶级查询。
我没有任何数据,所以我不确定我是否正确。希望对你有帮助。
所以我有这个查询:
SELECT c1.field1, c2.field2
FROM table1 c1
LEFT JOIN table1 c2 ON c1.field1 = c2.field1 AND c1.field2 = :arg1 AND c2.field2 <> :arg1
LEFT JOIN table2 cc ON c2.field2 = cc.field2 AND cc.field3 = :arg2
WHERE (c2.field2 IS NULL OR cc.field2 IS NOT NULL)
ORDER BY ISNULL(c2.field2) ASC
这有两件事:
- 为给定的
field2
值选择table1.field1
。 - 从第二个 table 中选取一个
table1.field2
,其中 field1 与前一点相同,也有一个特定的 属性。 (因为归一化才这么复杂)如果这不存在那么 returnNULL
.
虽然这行得通,但它真的很难看。有没有更简单的版本做同样的事情?我最烦恼的是第二个 JOIN
需要是一个 LEFT
,然后是这个 WHERE
。我觉得 INNER
应该更简单,但它不起作用。
尝试将左连接转移到union
和inner join
,然后你可以得到一个新的查询:
SELECT c1.field1, null as field2
FROM table1 c1
UNION ALL
SELECT c1.field1, c2.field2
FROM table1 c1
INNER JOIN table1 c2 ON c1.field1 = c2.field1
INNER JOIN table2 cc ON c2.field2 = cc.field2
WHERE c1.field2 = :arg1 AND c2.field2 <> :arg1 AND cc.field3 = :arg2
首先,我通过拆分 where 子句将您的原始查询从 join
转移到 union
:
SELECT c1.field1, c2.field2
FROM table1 c1
LEFT JOIN table1 c2 ON c1.field1 = c2.field1 AND c1.field2 = :arg1 AND c2.field2 <> :arg1
WHERE (c2.field2 IS NULL )
UNION ALL
SELECT c1.field1, c2.field2
FROM table1 c1
INNER JOIN table1 c2 ON c1.field1 = c2.field1 AND c1.field2 = :arg1 AND c2.field2 <> :arg1
LEFT JOIN table2 cc ON c2.field2 = cc.field2 AND cc.field3 = :arg2
WHERE (c2.field2 IS NOT NULL AND cc.field2 IS NOT NULL)
但是 union 的第一部分可以像这样保持传输:
SELECT c1.field1, null
FROM table1 c1
WHERE c1.field2 <> :arg1 --c2.field2 must be null
UNION ALL
SELECT c1.field1, c2.field2
FROM table1 c1
LEFT JOIN table1 c2 ON c1.field1 = c2.field1 AND c2.field2 <> :arg1
WHERE c1.field2 = :arg1 AND c2.field2 IS NULL
最后,我得到了将所有左连接转移到联合和内连接的顶级查询。
我没有任何数据,所以我不确定我是否正确。希望对你有帮助。