使用公共列拼接两个mysql表

时间:2012-08-17 09:15:34

标签: 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    |
+-------------+--------+--------+--------+--------+---------+

目前我手动迭代第二个表并更新第一个表中的相应行以实现此目的。我想到的其他方法是做一个外连接和 清理重复的行。是否有更好的方法来实现结果?

3 个答案:

答案 0 :(得分: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;

编辑更准确的查询:您需要为匹配的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 :(得分: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

答案 2 :(得分:0)

您需要显示这两个表之间的关系,而不是复制查询。规范化第一个表并使用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;