我不是问如何编写好的查询,但这3个查询返回相同的结果。
查询1
SELECT v1.id
FROM (
SELECT DISTINCT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL
) v1 INNER JOIN (
SELECT DISTINCT t3.id
FROM t3 LEFT JOIN t4 ON t3.id = t4.id
WHERE t4.id IS NULL
) v2 ON v1.id = v2.id;
查询2
SELECT DISTINCT t1.id
FROM (t1 LEFT JOIN t2 ON t1.id = t2.id)
INNER JOIN (t3 LEFT JOIN t4 ON t3.id = t4.id) ON t1.id = t3.id
WHERE t2.id IS NULL AND t4.id IS NULL;
查询3
SELECT DISTINCT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
INNER JOIN t3 ON t1.id = t3.id LEFT JOIN t4 ON t3.id = t4.id
WHERE t2.id IS NULL AND t4.id IS NULL;
查询不是由程序员硬编码,而是由用户输入动态生成。
例如,当用户插入find id in t1 (but not in t2) and in t3 (but not in t4)
时,他的缩进为Query 1
。但目前我的程序生成Query 3
,看起来还行。我想知道这个查询在某些情况下有一个错误,因此应该像Query 2
或1
一样进行更改。
用户输入(如上所示)只是示例,将用户输入转换为JOIN语句对我来说很难。
先谢谢。
答案 0 :(得分:1)
这是原始查询:
SELECT v1.id
FROM (SELECT DISTINCT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL
) v1 INNER JOIN
(SELECT DISTINCT t3.id
FROM t3 LEFT JOIN t4 ON t3.id = t4.id
WHERE t4.id IS NULL
) v2
ON v1.id = v2.id;
如果我理解正确,您需要id
和t1
中的t3
,而不是t2
和t4
中的SELECT distinct t1.id
FROM t1 INNER JOIN
t3
on t1.id = t3.id LEFT JOIN
t2
on t1.id = t2.id LEFT JOIN
t4
on t1.id = t4.id
WHERE t2.id IS NULL AND t4.id IS NULL;
。
我会将第二个查询表达为:
{{1}}
答案 1 :(得分:1)
我将原始查询读作要求“T1中的所有ID都在T1和T3中,但不在T2或T4中”。那是对的吗?如果是这样,我的查询将是:
SELECT DISTINCT t1.id
FROM t1
WHERE EXISTS (SELECT 1 FROM t3 WHERE t1.id = t3.id)
AND NOT EXISTS (SELECT 1 FROM t2 WHERE t1.id = t2.id)
AND NOT EXISTS (SELECT 1 FROM t4 WHERE t1.id = t4.id)
答案 2 :(得分:1)
不确定真正的目标是什么,也不确定目标是哪个dbms
-- oracle
SELECT id FROM ( SELECT id FROM t1 MINUS SELECT id FROM t2 ) a
INTERSECT
SELECT id FROM ( SELECT id FROM t3 MINUS SELECT id FROM t4 ) b
;
-- sql server
SELECT id FROM ( SELECT id FROM t1 EXCEPT SELECT id FROM t2 ) a
INTERSECT
SELECT id FROM ( SELECT id FROM t3 EXCEPT SELECT id FROM t4 ) b
;
SELECT c.id from (
SELECT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL
UNION ALL
SELECT t3.id
FROM t3 LEFT JOIN t4 ON t3.id = t4.id
WHERE t4.id IS NULL
) c GROUP BY c.id HAVING count(*) >= 2
;
下一个可能非常有效但是有一个警告
-- conditions apply, assumes t2 and t4 cannot have ids not in t1 or t3 respectively
SELECT c.id from (
SELECT a.id from (
(SELECT ID FROM T1)
UNION ALL
(SELECT ID FROM T2)
) a GROUP BY a.id HAVING count(*) = 1
UNION ALL
SELECT b.id from (
(SELECT ID FROM T3)
UNION ALL
(SELECT ID FROM T4)
) b GROUP BY b.id HAVING count(*) = 1
) c GROUP BY c.id HAVING count(*) >= 2
;