MYSQL - 如何将2行相关数据合并为1

时间:2017-10-12 19:20:14

标签: mysql

我是mysql的新手,并尝试研究它,但无法找到任何解决方案。我有一张这样的桌子:

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

让我们以前两行为例 第1行中的SW_Pair1 =第2行中的SW_Pair2 第2行中的SW_Pair1 =第1行中的SW_Pair2

我将它们放在下一行,但它们可以在数据库中的任何位置。现在我想合并这些2,以便第1行中的Pair1_VLAN1和Pair1_VLAN2中的数据进入第1行的Pair2_VLAN1和Pair2_VLAN2,然后第2行消失。因此,以下是合并后表格的外观:

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

依旧......

我正在使用python 2.7将数据推送到sql。

修改

我在下面尝试查询以在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;

或者更好的是,它可以在将数据移动到开关1之后设置第二个开关的Pair1_VLAN1和Pair1_VLAN2行的值吗?也许将vlan重写为类似" MERGED"。然后我可以安全地删除任何有" MERGED"在Pair1_VLAN1和Pair1_VLAN2中。我知道它只会说当它的数据成功移动到另一行时。

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;

4 个答案:

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

答案 1 :(得分:1)

我确信有更简洁的方法可以做到这一点,但这是我提出的一种黑客方式。

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

我正在使用模数(%2)来确保我们只在第一列中获得奇数,因此在第2列中使用偶数。我很想知道其他人是否可以想出比我更清洁的解决方案。如果是这样,那将有助于我不时做一些事情。

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

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

希望它有所帮助!