结合INNER JOIN和LEFT JOIN

时间:2014-09-19 00:59:59

标签: sql

被修改

我不是问如何编写好的查询,但这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 21一样进行更改。

用户输入(如上所示)只是示例,将用户输入转换为JOIN语句对我来说很难。

先谢谢。

3 个答案:

答案 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;

如果我理解正确,您需要idt1中的t3,而不是t2t4中的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
;

小提琴: | Oracle | SQL Server | MySQL |