2014-09-19 120 views
0

編輯

我不是問如何編寫好的查詢,但這3個查詢返回相同的結果。結合INNER JOIN和LEFT JOIN

查詢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,它看起來像確定。我想知道這個查詢在某些情況下有bug,所以應該改爲Query 21

用戶輸入(如上所示)僅僅是一個例子,最終我很難將用戶輸入轉換爲JOIN語句。

謝謝先進。

+0

關於修改/澄清的問題:如果表中有相同id值的倍數,我相信* Query 3 *將產生與* Query 1 *不同的結果。 – Turophile 2014-09-19 05:41:12

+0

@嗜熱者哎呀。它是*錯字*。固定。謝謝。 – 2014-09-19 06:09:31

+0

問題到底是什麼?是這樣的:**「我想知道這個查詢在某些情況下有bug」**你有任何失敗測試用例嗎? – 2014-09-19 10:05:48

回答

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 S中的在t1t3,但不是在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; 
+0

對不起,延遲迴復。 「你想要t1和t3中的id,而不是t2和t4」=>是的!我已經更新了我的問題。 – 2014-09-19 02:21:59

1

我看了你的原始查詢的要求「在T1這是在T1和T3但不是在T2和T4所有ID」:

,我謹表示第二個查詢。那是對的嗎?如果是這樣,我的查詢將是:

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) 
+0

謝謝你有時間。 SEMI JOIN被認爲是下一個產品中的一對多關係。另外我更新了我的問題。 – 2014-09-19 02:23:07

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 |