2011-10-08 146 views
1

長時間用戶,第一次張貼海報。我發現了類似的問題/答案,通常涉及子查詢,但我不知道如何適用於我的情況。mysql - 兩個左連接 - 雙重計數

我有3個表:

table1 
id 

table2 
id | val (each id has 1 of 3 possible values) 

table3 
id | val (each id has 1 of 3 possible values) 

編輯:例如:(表1 =每個人的唯一的ID誰參加了一個主題公園,表2 =每個訪問者訪問了哪些景點第一;表3 =其吸引每個訪問者訪問第二)。

我想編寫一個查詢查找7個不同的計數: (1)在表1的唯一ID的數量 (2)讓每個可能的值在表2 ID數的計數(3具有每一個可能值的表3中的ID的數量)計數

我的MySQL查詢:

SELECT 
    count(DISTINCT table1.id) AS x1, 
    SUM(IF(table2.val='1'),1,0)) AS x2, 
    SUM(IF(table2.val='2'),1,0)) AS x3, 
    SUM(IF(table2.val='3'),1,0)) AS x4, 
    SUM(IF(table3.val='1'),1,0)) AS x5, 
    SUM(IF(table3.val='2'),1,0)) AS x6, 
    SUM(IF(table3.val='3'),1,0)) AS x7 
FROM 
    table1 
LEFT JOIN 
    table2 ON table1.id=table2.id 
LEFT JOIN 
    table3 ON table1.id=table3.id 

結果:

X1 =正確的(因爲DISTINCT)

X2,X3,X4 =正確

X5,X6,X7 = TWICE他們應該是多少(因爲我得到笛卡爾積?)

有什麼建議?

+0

您是否考慮過在子查詢中單獨計算表,然後連接兩個子查詢的結果? –

+0

這可能是我需要做的,但是我從來沒有做過再次選擇,也不知道如何以這種方式重新編寫我的查詢。 – egret

+0

用戶錯誤。原來我在表2中有重複的記錄.ID應該是唯一的,但不能強制在表定義中。因此重複計算。感謝所有對此評論的人。嘗試每一個建議幫助我理解發生了什麼。 – egret

回答

1

我的猜測是你的問題是,該編號在table1中不是唯一的。因此,儘管它在table2/3(根據您的描述)中是唯一的,但table2/3中的每一行都連接到table1中的兩行,因此計數兩次。與左連接無關,正常的內連接會有同樣的問題。

如果MySQL(我不知道真正的好),讓你做內聯的意見,如Oracle的話,那麼你可以寫你的查詢作爲解決這個問題:

SELECT 
    count(view1.id)    AS x1, 
    SUM(IF(table2.val='1'),1,0)) AS x2, 
    SUM(IF(table2.val='2'),1,0)) AS x3, 
    SUM(IF(table2.val='3'),1,0)) AS x4, 
    SUM(IF(table3.val='1'),1,0)) AS x5, 
    SUM(IF(table3.val='2'),1,0)) AS x6, 
    SUM(IF(table3.val='3'),1,0)) AS x7 
FROM 
    ( SELECT DISTINCT table1.id 
     FROM table1 
    ) view1 
LEFT JOIN 
    table2 ON view1.id=table2.id 
LEFT JOIN 
    table3 ON view1.id=table3.id 
+0

表1中的ID是唯一的。例如:(table1 =參加主題公園的每個人的唯一ID; table2 =每個參觀者首先參觀的吸引力; table3 =每個參觀者參觀的吸引力次之)。我將編輯我的原始帖子以添加此(重要/有用)信息。 – egret

+0

用戶錯誤。原來我在表2中有重複的記錄.ID應該是唯一的,但不能強制在表定義中。因此重複計算。這可能是最正確的答案,因爲它確定了id不是唯一的可能性。謝謝。 – egret

0

我會刪除每個重複表:

SELECT 
    count(t1.id) AS t1, 
    SUM(IF(t2.val=1,1,0)) AS t21, 
    SUM(IF(t2.val=2,1,0)) AS t22, 
    SUM(IF(t2.val=3,1,0)) AS t23, 
    SUM(IF(t3.val=1,1,0)) AS t31, 
    SUM(IF(t3.val=2,1,0)) AS t32, 
    SUM(IF(t3.val=3,1,0)) AS t33 
FROM (SELECT DISTINCT * FROM table1) as t1 
JOIN (SELECT DISTINCT * FROM table2) as t2 ON t1.id=t2.id 
JOIN (SELECT DISTINCT * FROM table3) as t3 ON t1.id=t3.id; 
+0

我讚賞這個建議,但沒有解決重複計算。 – egret

2

您將得到笛卡爾結果。由於您沒有顯示每個「ID」有多少「1」,「2」或「3」計數,只需從這些表中自行選擇sum()。由於沒有分組的總和將總是產生一條記錄,所以不需要任何連接,並且它將拉取每個總結的一條記錄的結果而不會產生笛卡爾結果。由於您的原始查詢是LEFT JOIN的其他人,該ID將已經存在於表1,所以爲什麼在每個子表中重新查詢計數不同。

SELECT 
     SumForTable1.x1, 
     SumForTable2.x2, 
     SumForTable2.x3, 
     SumForTable2.x4, 
     SumForTable3.x5, 
     SumForTable3.x6, 
     SumForTable3.x7 
    FROM 
     (select count(DISTINCT table1.id) AS x1 
      from table1) SumForTable1, 

     (select SUM(IF(table2.val='1'), 1, 0)) AS x2, 
       SUM(IF(table2.val='2'), 1, 0)) AS x3, 
       SUM(IF(table2.val='3'), 1, 0)) AS x4 
      from table2) SumForTable2, 

     (select SUM(IF(table3.val='1'), 1, 0)) AS x5, 
       SUM(IF(table3.val='2'), 1, 0)) AS x6, 
       SUM(IF(table3.val='3'), 1, 0)) AS x7 
      from table3) SumForTable3 
+0

這將在MySQL中工作,但您可能想寫'CROSS JOIN'而不是'JOIN'來指出這些連接真的是什麼。 –

+0

我認爲「笛卡兒結果」是重複計數的原因。我必須爲table1中的每個id計算一次table3記錄,並且每次在表2中顯示相同的id。但是,我無法讓您的示例執行。我嘗試了一些東西 - 重新寫了幾個方法 - 但仍然沒有運氣。 – egret

+0

@egret,對不起,我知道你已經有你的答案明顯解決了,但我改變了這一點。由於沒有「JOIN」進入,我只用逗號分隔FROM來源,這將允許笛卡爾1:1:1全部合併在一起。 – DRapp