2013-05-29 59 views
0

我有一個數據庫(MySQL 5.1),它使用交叉引用表(local_ref,在下面的示例中)獲取值的數字ID。我已經引入了另一個交叉引用表(下面的foreign_ref)來將這些數字ID引用到另一個數據庫中的索引。通常情況下,這不是一個複雜的連接,但是,我有多個使用交叉引用表(下面的val1和val2)中的鍵的列。基於兩個交叉引用表連接多個表

如:

mysql> select * from foo; 
+-----+------+------+ 
| id | val1 | val2 | 
+-----+------+------+ 
| 100 | A | B | 
| 200 | A | D | 
| 300 | B | C | 
+-----+------+------+ 

mysql> select * from local_ref; 
+----+-------+ 
| id | value | 
+----+-------+ 
| 1 | A  | 
| 2 | B  | 
| 3 | C  | 
| 4 | D  | 
| 5 | E  | 
+----+-------+ 

mysql> select * from foreign_ref; 
+----------+------------+ 
| local_id | foreign_id | 
+----------+------------+ 
|  1 |   10 | 
|  2 |   20 | 
|  3 |   30 | 
|  4 |   40 | 
+----------+------------+ 

我需要的是以下幾點:

+-----+---------+---------+ 
| id | val1_id | val2_id | 
+-----+---------+---------+ 
| 100 | 10  | 20  | 
| 200 | 10  | 40  | 
| 300 | 20  | 30  | 
+-----+---------+---------+ 

知道,原來的表不歸,因爲它應該是,我已經取得的成果,下面的兩個方式:

將兩個交叉參考表重複兩次:

SELECT 
FOO.id, F_R1.foreign_id, F_R2.foreign_id 
FROM FOO 
JOIN 
Local_Ref as L_R1 ON (FOO.val1 = L_R1.value) 
JOIN 
Local_Ref as L_R2 ON (FOO.val2 = L_R2.value) 
JOIN 
Foreign_Ref as F_R1 ON (L_R1.id = F_R1.local_id) 
JOIN 
Foreign_Ref as F_R2 ON (L_R2.id = F_R2.local_id) 

加入交叉引用表兩次並混淆每個連接。

SELECT 
FOO.id, joint1.foreign_id, joint2.foreign_id 
FROM 
FOO 
JOIN 
(
SELECT * FROM Local_Ref JOIN Foreign_Ref ON Local_Ref.id = Foreign_Ref.local_id 
) as joint1 
ON FOO.val1 = joint1.value 
JOIN 
(
SELECT * FROM Local_Ref JOIN Foreign_Ref ON Local_Ref.id = Foreign_Ref.local_id 
) as joint2 
ON FOO.val2 = joint2.value 

我覺得這兩種方法相當低效,可以改進。除了重建數據庫之外,還有沒有更有效的解決方案?

+0

你的方法很好。 –

回答

0

如果你不能重構foo表,那麼另一種獲得結果的方式是unpivot該表中的數據。

MySQL沒有unpivot函數,但是您使用了UNION ALL查詢。

的基本語法爲:

select id, 'val1' col, val1 value 
from foo 
union all 
select id, 'val2' col, val2 value 
from foo 

Demo

這將去歸表的多個列轉換爲多行哪一個更容易加入的。一旦數據是這種格式,那麼你可以加入其他表格一次,而不是兩次。最後,您可以應用聚合函數CASE表達式的值轉換爲列:

select f.id, 
    max(case when f.col = 'val1' then fr.foreign_id end) val1_id, 
    max(case when f.col = 'val2' then fr.foreign_id end) val2_id 
from 
(
    select id, 'val1' col, val1 value 
    from foo 
    union all 
    select id, 'val2' col, val2 value 
    from foo 
) f 
inner join local_ref l 
    on f.value = l.value 
inner join foreign_ref fr 
    on l.id = fr.local_id 
group by f.id 

SQL Fiddle with Demo。這給出了一個結果:

| ID | VAL1_ID | VAL2_ID | 
--------------------------- 
| 100 |  10 |  20 | 
| 200 |  10 |  40 | 
| 300 |  20 |  30 | 
+0

感謝您的詳細回覆。我現在最終使用了別名,但我可能最終會在將來使用它。 – Kyle