2012-08-17 47 views
2

我有兩個表這樣,針兩次與公共列MySQL表

表1:

+-------------+--------+--------+--------+ 
| contract_id | price1 | price2 | price3 | 
+-------------+--------+--------+--------+ 
|   1 |  23 |  45 |  56 | 
|   1 |  22 |  21 | 453 | 
|   1 |  45 | 564 | 456 | 
|   4 |  22 |  21 | 453 | 
|   5 |  45 | 564 | 456 | 
+-------------+--------+--------+--------+ 

和表2,

+-------------+--------+---------+ 
| contract_id | owner | address | 
+-------------+--------+---------+ 
|   1 | Me  | Madras | 
|   1 | father | Chennai | 
+-------------+--------+---------+ 

我想縫兩個表在一起,結果看起來像,

+-------------+--------+--------+--------+--------+---------+ 
| contract_id | price1 | price2 | price3 | owner | address | 
+-------------+--------+--------+--------+--------+---------+ 
|   1 |  23 |  45 |  56 | Me  | Madras | 
|   1 |  22 |  21 | 453 | father | Chennai | 
|   1 |  45 | 564 | 456 | NULL | NULL | 
|   4 |  22 |  21 | 453 | NULL | NULL | 
|   5 |  45 | 564 | 456 | NULL | NULL | 
+-------------+--------+--------+--------+--------+---------+ 

目前我手動迭代第二個表並更新第一個表中的相應行以實現此目的。我想到的其他方法是做一個外連接並清理重複的行。有沒有更好的方法來達到結果?

+0

你什麼重複的行? – Thilo 2012-08-17 09:26:16

+0

@Thilo它們本身不是重複的行。但是當我參加時。左側的前3條記錄與右側的2條記錄相匹配,因爲我正在與contract_id進行連接,因此總共返回6行。我想要的結果有點不同。 – tamizhgeek 2012-08-17 09:28:12

+0

爲什麼一行'contract_id = 1'應該與'Me-Madras'有關,另一個與'father-Chennai'有關,而另一個根本沒有? – 2012-08-17 09:38:55

回答

1

我們必須都要加入表由它Row_Number.

試試這個:

SELECT a.contract_id, a.price1, a.price2, a.price3, b.owner, b.address 
FROM (SELECT contract_id, price1, price2, price3, (@rank := @rank + 1) AS rank 
     FROM t1, (SELECT @rank := 0) tmp 
    )a 
LEFT JOIN 
    (SELECT contract_id, owner, address, (@rank1 := @rank1 + 1) AS rank 
     FROM t2, (SELECT @rank1 := 0) tmp 
    )b 
ON a.rank = b.rank 
AND a.contract_id = b.contract_id 
ORDER BY a.rank ASC; 

See this SQLFiddle

+0

那是UNION模擬一個OUTER JOIN嗎? – Thilo 2012-08-17 09:18:33

+0

這就是我現在正在做的。但這不是一個完整的答案。我必須模擬這個外部連接並清理結果集以獲得我想要的結果。 – tamizhgeek 2012-08-17 09:22:07

+0

@tamizhgeek查看帶小提琴的更新答案。 – hims056 2012-08-17 09:53:43

2

這應該很好地工作。首先,我計算兩個表的排名,然後根據排名使用LEFT JOIN加入這兩個表,以便輸出中不會有任何重複,因爲它是一對一映射。

嘗試此查詢:

SELECT 
    a.contract_id, a.price1, a.price2, a.price3, b.owner, b.address 
FROM 
    (SELECT 
     contract_id, price1, price2, price3, (@rank := @rank + 1) AS rank 
    FROM 
     table1, (SELECT @rank := 0) tmp) a 
LEFT JOIN 
    (SELECT 
     contract_id, owner, address, (@rank := @rank + 1) AS rank 
    FROM 
     table2, (SELECT @rank := 0) tmp) b ON a.rank = b.rank 
ORDER BY 
    a.rank ASC; 

EDITED更準確QUERY:你需要匹配contract_ids創建嵌套排名:

SELECT 
    a.c_id, a.price1, a.price2, a.price3, b.owner, b.address 
FROM 
    (SELECT 
     @var_rank := IF(contract_id <> @var_id_prev,1, @var_rank+1) AS vrank, 
     @var_id_prev := contract_id AS c_id, 
     price1, price2, price3, @rank := (@rank + 1) AS rnk 
    FROM 
     table1, (SELECT @var_id_prev := 0) tmp 
    ORDER BY 
     contract_id) a 
LEFT JOIN 
    (SELECT 
     @var_rank := IF(contract_id <> @var_id_prev, 1, 
     @var_rank+1) AS vrank, 
     @var_id_prev := contract_id AS c_id, 
     owner, address, @rank := @rank + 1 AS rnk 
    FROM 
     table2, (SELECT @var_id_prev := 0) tmp 
    ORDER BY 
     contract_id) b ON a.c_id = b.c_id AND a.vrank = b.vrank 
ORDER BY 
    a.c_id, a.vrank ASC; 

SQL FIDDLE DEMO HERE

但更好的方法是在兩個表上放置auto id並在連接狀態下使用。

通過這種表是標準化的,這將節省創建內部內存臨時表在計算排名的額外開銷。它還將通過在這些連接的列上使用索引來加速查詢。

+1

你想解釋'auto id'會如何幫助嗎? – 2012-08-17 09:58:26

+0

你確定。請參閱我的文章的最後部分。 – Omesh 2012-08-17 10:04:39

+0

這在一定程度上起作用。但它正在折扣contract_id列。拼接只能在具有相同contract_id的行之間進行。 – tamizhgeek 2012-08-17 11:00:46

0

相反comlicating查詢的,你需要證明這兩個表之間的關係。對第一個表進行標準化並使用foreign key來交叉引用相關數據。我會做這樣的:

enter image description here

查詢看起來像:

SELECT table1.contract_id, table1.price1, table1.price2, table1.price3, table2.name, table2.address 
FROM table1 
LEFT JOIN table2 ON table1.owner_id = table2.id; 
+0

t1和t2基本上是從子查詢派生的表。 – tamizhgeek 2012-08-17 11:04:12

+1

@tamizhgeek那麼你應該提供你正在使用的原始表格結構和查詢,以便SO社區能夠幫助你。 – mintobit 2012-08-17 11:07:07