2017-10-12 9 views
1

私はmysqlを初めて使っていて、それを研究しようとしましたが、解決策は見つかりませんでした。私はこのようなテーブルを持っています:関連するデータの2行を1にマージする方法

| SW_Pair1  | SW_Pair2  | Pair1_VLAN1| Pair1_VLAN2| Pair2_VLAN1| Pair2_VLAN2| Inter | Mgmt| OSPF| Env | Domain| 
    |-----------------|-----------------|------------|------------|------------|------------|-------|-----|-----|-----|-------| 
    | Switch1.abc.com | Switch2.abc.com | VLAN-111 | VLAN-333 | Unknown | Unknown | 47 | 24 | 0.1 | Dev | abc | 
    | Switch2.abc.com | Switch1.abc.com | VLAN-222 | VLAN-444 | Unknown | Unknown | 47 | 24 | 0.1 | Dev | abc | 
    | Switch3.abc.com | Switch4.abc.com | VLAN-121 | VLAN-123 | Unknown | Unknown | 47 | 24 | 0.1 | Dev | abc | 
    | Switch4.abc.com | Switch3.abc.com | VLAN-515 | VLAN-717 | Unknown | Unknown | 47 | 24 | 0.1 | Dev | abc | 
    | Switch5.abc.com | Switch6.abc.com | VLAN-919 | VLAN-101 | Unknown | Unknown | 47 | 24 | 0.1 | Dev | abc | 
    | Switch6.abc.com | Switch5.abc.com | VLAN-105 | VLAN-108 | Unknown | Unknown | 47 | 24 | 0.1 | Dev | abc | 
    | Switch7.abc.com | Switch8.abc.com | VLAN-110 | VLAN-115 | Unknown | Unknown | 47 | 24 | 0.1 | Dev | abc | 
    | Switch8.abc.com | Switch7.abc.com | VLAN-199 | VLAN-200 | Unknown | Unknown | 47 | 24 | 0.1 | Dev | abc | 

最初の2行を例にとります。行1

の行で
SW_Pair1行2 == SW_Pair2の行2 SW_Pair1で1 == SW_Pair2私は次の行に入れますが、彼らは、データベース内の任意の場所にすることができます。ここでは、2行目のPair1_VLAN1とPair1_VLAN2のデータが1行目のPair2_VLAN1とPair2_VLAN2に入り、2行目が消えるようにこれらの2つをマージしたいと考えています。私はSQLにデータをプッシュするのpython 2.7を使用しています

| SW_Pair1  | SW_Pair2  | Pair1_VLAN1| Pair1_VLAN2| Pair2_VLAN1| Pair2_VLAN2| Inter | Mgmt| OSPF| Env | Domain| 
|-----------------|-----------------|------------|------------|------------|------------|-------|-----|-----|-----|-------| 
| Switch1.abc.com | Switch2.abc.com | VLAN-111 | VLAN-333 | VLAN-222 | VLAN-444 | 47 | 24 | 0.1 | Dev | abc | 
| Switch3.abc.com | Switch4.abc.com | VLAN-121 | VLAN-123 | VLAN-515 | VLAN-717 | 47 | 24 | 0.1 | Dev | abc | 

など..

:だから、ここの表は、マージ後にどのように見えるべきかです。

編集:

私はDELETEの上に追加のチェックを追加するために、クエリの下にしようとしたが、それは失敗しました:

UPDATE yourTable AS a 
DELETE FROM yourTable AS b ON a.SW_Pair1 = b.SW_Pair2 AND a.SW_Pair2 = b.SW_Pair1 
WHERE Pair2_VLAN1 IS Unknown; 

以上、それは後の第2スイッチのPair1_VLAN1とPair1_VLAN2行の値を設定することができますスイッチ1にデータを移動しますか?おそらく、 "MERGED"のようなものにVLANを上書きするでしょう。私は安全にPair1_VLAN1とPair1_VLAN2に "MERGED"を持つものをすべて削除できます。私はそれがデータが正常に別の行に移動されたときだけそれが言うことを知っている。

EDIT2:

NVMは...それを考え出しました。以下を参照してください:

UPDATE yourTable AS a 
JOIN yourTable AS b ON a.SW_Pair1 = b.SW_Pair2 AND a.SW_Pair2 = b.SW_Pair1 
SET a.Pair2_VLAN1 = b.Pair1_VLAN1, 
    a.Pair2_VLAN2 = b.Pair1_VLAN2, 
    b.Pair1_VLAN1 = "MERGED", 
    b.Pair1_VLAN2 = "MERGED 
WHERE a.SW_Pair1 < a.SW_Pair2; 
+0

マージされたデータを表示したいだけですか、実際にマージされたデータをテーブルに保存したいのですか? –

+0

それを保存し、他の行を削​​除します。 – Damon

答えて

2

最初に一致する行からのデータと、各対の最初の行を更新:

UPDATE yourTable AS a 
JOIN yourTable AS b ON a.SW_Pair1 = b.SW_Pair2 AND a.SW_Pair2 = b.SW_Pair1 
SET a.Pair2_VLAN1 = b.Pair1_VLAN1, 
    a.Pair2_VLAN2 = b.Pair1_VLAN2 
WHERE a.SW_Pair1 < a.SW_Pair2; 

WHERE句は、各ペア(SW_Pair1に低い名前を持つもの)で唯一の行が更新されることを保証します。

次に、更新されていない行を削除します。最初のクエリで更新された列にはまだNULLが残っています。

DELETE FROM yourTable 
WHERE Pair2_VLAN1 IS NULL; 

これはすべてに一致する行があることを前提としています。より安全なものが必要な場合は、反対の名前の行があることを確認する結合を行う必要があります。

DELETE a FROM yourTable AS a 
JOIN yourTable AS b ON a.SW_Pair1 = b.SW_Pair2 AND a.SW_Pair2 = b.SW_Pair1 
WHERE a.Pair2_VLAN1 IS NULL 
+0

これは完全に機能しました。とにかく、DELETEのチェックをいくつか追加して、ペアのないスイッチを削除しないのですか?私はクエリを策定しようとしましたが、SQLエラーが発生しました。私の編集を見てください。 – Damon

+0

あなたは一つの文で 'UPDATE'と 'DELETE'を組み合わせません。 – Barmar

+0

チャームのように働いた、ありがとう。最後の質問ですが、データをスイッチ1に移動した後、2番目のスイッチのPair1_VLAN1とPair1_VLAN2の値を設定することは可能ですか?おそらく、 "MERGED"のようなものにVLANを上書きするでしょう。 'SET a.'SEC_BB_A' = b.'PRI_BB_A'、 a.'SEC_BB_B' = b.'PRI_BB_B' b.'PRI_BB_A' = MERGED b.'PRI_BB_B' = MERGED' – Damon

1

私はこれを行うにはクリーンな方法があると確信しているが、これは私が思い付いたハック方法です。私はどうかを確認することが、私は好奇心旺盛になると思い列2の偶数番号を持つ、我々は唯一の最初の列に奇数を得ることを確認するために剰余(%2)を使用してい

select 
a.sw_pair1, 
a.sw_pair2, 
a.pair1_vlan1, 
a.pair2_vlan1 as pair1_vlan2, 
b.pair1_vlan1 as pair2_vlan1, 
b.pair2_vlan1 as pair2_vlan2 

from TABLENAME a 
join TABLENAME b on a.sw_pair1 = b.sw_pair2 
where cast(substring_index(substring_index(a.sw_pair1, '.abc.com', 1), 'Switch', -1) as unsigned) % 2 > 0 

他の誰か私がやったより洗練されたソリューションを思いつくことができます。もしそうなら、それは私が時々行うことのいくつかを助けてくれるでしょう。

+1

別のアプローチについて興味がある場合に備えて、私の答えを見ているかもしれません。それが助けになることを願っています。 –

+0

素晴らしいです。コメントしてくれてありがとう、私はそれを参照してください。間違いない。 –

+0

喜んで助けてください。親切なupvote将来の訪問者に役立つようにする。ありがとうございました。 –

1

この方法は現在の回答よりも簡単です。これにより、サンプルデータから希望する出力が得られました。

SELECT 
a.SW_Pair1, 
a.SW_Pair2, 
a.Pair1_VLAN1, 
a.Pair1_VLAN2, 
b.Pair1_VLAN1 as Pair2_VLAN1, 
b.Pair1_VLAN2 as Pair2_VLAN2 
FROM test as a , test as b 
WHERE a.SW_Pair1 = b.SW_Pair2 AND a.SW_Pair2>b.SW_Pair2; 
1

マージしたデータをテーブルに保存する場合は、@ Barmarのソリューションが完全に機能します。あなただけのクエリ、次のデータを表示したい場合は

は、しかし、仕事を得るだろう:

select least(t1.SW_Pair1,t1.SW_Pair2),greatest(t1.SW_Pair1,t1.SW_Pair2), 
     t2.Pair1_VLAN1,t2.Pair1_VLAN2, 
     t1.Pair1_VLAN1 as Pair2_VLAN1,t1.Pair1_VLAN2 as Pair2_VLAN2 
from tablet1 as t1 
inner join tablet2 as t2 
on t2.SW_Pair1 = t1.SW_Pair2 and t2.SW_Pair2=t1.SW_Pair1 
group by least(t1.SW_Pair11,t1.SW_Pair2),greatest(t1.SW_Pair1,t1.SW_Pair2); 

はそれが役に立てば幸い!

関連する問題