2015-09-07 77 views
0

我試圖找到只存在於一個表中的行。大表名(由所有行組成)是kwf_uploads,以許多名字出現的小表。我的目標是找到存在於kwf_uploads中的行,但不存在於其他位置(這個例子是沒有關係的表中的主鍵和外鍵)。如何將表與多個工會進行比較並加入?

我在SQL做了什麼:

select id from 
kwf_uploads 
left join 

(SELECT picture_id as id 
FROM documents where picture_id is not null 
UNION 
SELECT file_id as id 
FROM books where file_id is not null 
UNION 
SELECT picture_id as id 
FROM employee where picture_id is not null 
UNION 
SELECT file_id as id 
FROM flightFiles where file_id is not null 
UNION 
SELECT picture_id as id 
FROM tasks where picture_id is not null 
UNION 
SELECT picture_id as id 
FROM trainingContentQuestions where picture_id is not null 
UNION 
SELECT picture_id as id 
FROM trainingQuestions where picture_id is not null) foo 

ON kwf_uploads.id = foo.id 

找到它:SQL: cascade UNION and JOIN

但它失敗,錯誤:SQL (1052): Column "id" in field list is ambiguous

我不想在每個表中使用連接,因爲我不擅長連接,並且sql變得非常大且不可讀。我也試過not exists沒有任何結果。 我認爲,我們可以找到一個更好的解決方案=)

導致select id from kwf_uploads查詢(9690行):

enter image description here

從聯合查詢結果(6096行):

enter image description here

結果我想看到3594(9690減去6096)行。

+1

您的問題不是很清楚。向我們展示一些數據並期待結果。順便說一句,因爲你不擅長某事並不意味着你無法學習。 '加入'是最好的工具。 –

+0

@JuanCarlosOropeza完成。 – Sogl

+0

所以'上傳'='工會(文件,書籍,員工,飛行文件,任務,培訓內容問題,訓練問題)' –

回答

3

UNION(單獨使用時,沒有ALL)是一個「昂貴」的操作。

有一個替代方案,不存在。這個構造是一個「半連接」,我懷疑可能比聯合方法更便宜。

SELECT 
     id 
FROM kwf_uploads AS u 
WHERE NOT EXISTS  (SELECT NULL FROM documents WHERE u.id = picture_id) 
     AND NOT EXISTS (SELECT NULL FROM books WHERE u.id = file_id) 
     AND NOT EXISTS (SELECT NULL FROM employee WHERE u.id = picture_id) 
     AND NOT EXISTS (SELECT NULL FROM flightFiles WHERE u.id = file_id) 
     AND NOT EXISTS (SELECT NULL FROM tasks WHERE u.id = picture_id) 
     AND NOT EXISTS (SELECT NULL FROM trainingContentQuestions WHERE u.id = picture_id) 
     AND NOT EXISTS (SELECT NULL FROM trainingQuestions WHERE u.id = picture_id) 
+0

也許'聯合'是昂貴的,但是每行存在7看起來也很昂貴。 –

+1

幾乎沒有工會那麼昂貴。 EXISTS/NOT EXISTS的效率非常高,因爲它的行爲就像一個連接,但不必將任何數據「拉」到結果集中。順便一提;永遠不要假設簡短的SQL代碼等於該代碼更高效的操作。通常情況恰恰相反。 –

+0

你對!重新啓動mysql進程後檢查我的本地主機。與'聯盟'1,482秒。 (+ 1,607秒網絡)和'不存在'0,109秒。 (+109秒網絡)。 – Sogl

1

要解決當前的錯誤與正確的結果集別名

前綴ID列。在這種情況下,kwf_uploads.id。由於Id存在於兩個結果集中。

,從而獲得所需的輸出

添加Where foo.id is null。這將獲取那些加入失敗的ID,那些是你想要的ID。

select kwf_uploads.id from 
     kwf_uploads 
     left join 

     (SELECT picture_id as id 
     FROM documents where picture_id is not null 
     UNION 
     SELECT file_id as id 
     FROM books where file_id is not null 
     UNION 
     SELECT picture_id as id 
     FROM employee where picture_id is not null 
     UNION 
     SELECT file_id as id 
     FROM flightFiles where file_id is not null 
     UNION 
     SELECT picture_id as id 
     FROM tasks where picture_id is not null 
     UNION 
     SELECT picture_id as id 
     FROM trainingContentQuestions where picture_id is not null 
     UNION 
     SELECT picture_id as id 
     FROM trainingQuestions where picture_id is not null) foo 

     ON kwf_uploads.id = foo.id 
     where foo.id is null 
+0

評論會很好。 –

+0

我想念表名...... thx!我不明白爲什麼使用'foo.id爲空'我們得到了期望的結果?我在之前的每個聯盟中都看到「不是空」。 – Sogl

+1

@Sogl:你正在做這個條件爲'ON kwf_uploads.id = foo.id'的表和聯合結果集之間的左連接。即使右表沒有匹配,左連接也會從左表中獲取所有結果。因此,在最終結果集中,如果您將foo.id視爲null,則表示它們存在於第一個表中,但不是第二個。嘗試刪除'where foo.id爲空'並查看結果。你會明白的。 – DarkKnight

1

除了DarkKnight答案:

您不需要包括每個union selectwhere。最糟糕的情況下,你從所有UNION得到一個NULL但不會出現在LEFT JOIN反正

select kwf_uploads.id 
from kwf_uploads 
left join 
    (
    SELECT picture_id as id FROM documents 
    UNION 
    SELECT file_id as id FROM books 
    UNION 
    SELECT picture_id as id FROM employee 
    UNION 
    SELECT file_id as id FROM flightFiles 
    UNION 
    SELECT picture_id as id FROM tasks 
    UNION 
    SELECT picture_id as id FROM trainingContentQuestions 
    UNION 
    SELECT picture_id as id FROM trainingQuestions 
    ) foo  
ON kwf_uploads.id = foo.id 
where foo.id is null 
+0

謝謝,它的作品應該!但我不明白爲什麼它與'foo.id is null'一起工作,而且沒有工作。 =)Union選項顯示我1 NULL – Sogl

+1

因爲即使當'union'有一個'null',連接的左邊沒有任何'null'。所以沒有匹配。 –

+1

如果你堅持對這個查詢使用聯合方法,你可以節省費用並使用'UNION ALL'獲得相同的結果。在這個查詢中,如果一個上傳ID在多個表中使用,則無關緊要,因爲您正在查找那些根本沒有引用的上傳ID。所以,請幫個忙,使用'UNION ALL'代替。 –

相關問題