2

私はこのような2つのテーブルを持っています、

表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    |
+-------------+--------+--------+--------+--------+---------+

現在、2番目のテーブルを手動で反復処理し、これを実現するために最初のテーブルの対応する行を更新しています。私が理解した他のアプローチは、外部結合を実行し、重複する行をクリーンアップすることです。結果を達成するためのより良い方法はありますか?

4

3 に答える 3

2

これは完全に機能するはずです。最初に両方のテーブルのランクを計算し、次にLEFT JOINランクに基づいてこれら2つのテーブルを結合して、1対1のマッピングであるため出力に重複がないようにします。

このクエリを試してください:

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フィドルデモはこちら

ただし、より良いアプローチはauto id、両方のテーブルを配置し、それを結合条件で使用することです。

これを行うことにより、テーブルは正規化され、ランクの計算中にメモリ内に一時テーブルを作成するための追加のオーバーヘッドを節約できます。また、これらの結合された列のインデックスを使用してクエリを高速化します。

于 2012-08-17T09:35:47.967 に答える
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;

このSQLFiddleを参照してください

于 2012-08-17T09:17:11.133 に答える
0

クエリを複雑にする代わりに、これら2つのテーブル間の関係を示す必要があります。最初のテーブルを正規化し、外部キーを使用して関連データを相互参照します。私はこのようにします:

ここに画像の説明を入力してください

クエリは次のようになります。

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;
于 2012-08-17T09:56:34.880 に答える