2012-09-17 40 views
1

我有一个客户提供的数据集,看起来像这样:(简体)MySQL的分裂多列到多行

|ForiegnKey|Code1|Code2|Code3| 
|==========|=====|=====|=====| 
|A   |10 |20 |30 | 
|A   |10 |20 |30 | 
|B   |100 |200 |  | 
|C   |25 |35 |40 | 
|D   |1000 |  |  | 
|E   |  |  |9999 | 

最终产品,我需要这个进入了一个新的表1中的代码在一个时间,所以像这样:

|ForiegnKey|Sequence|Code| 
|A   |1  |10 | 
|A   |2  |20 | 
|A   |3  |30 | 
|B   |1  |100 | 
|C   |1  |25 | 
|C   |2  |35 | 
|C   |3  |40 | 
|D   |1  |1000| 
|E   |1  |9999| 

对于我的问题,有一个简单的方法,这样做一个查询不使用工会参与?
我必须根据ForiegnKey的值生成序列号(即在ForiegnKey E的情况下,即使是在列Code3中,我也需要它具有1的序列)。我目前的思路是如果我可以在不使用Union的情况下将其从表中除去,那么我可以在同一个语句中生成Sequence ID。
应该跳过空的代码值,例如D-2和3以及E-1和2。
我已经开始使用临时表来处理这个问题,但我想我会在这里查看是否有更简单的方法。

感谢

+0

我知道你不希望使用联合查询,但你可以实现你被放在联合查询在子选择和使用您的FROM子句中寻找什么? – Tom

+0

我会用'UNION'去。 – Kermit

+0

您可以编写一个存储过程,它将逐行遍历表,检查代码列并将记录插入到新表中。 – Michael

回答

2

您的声音更感兴趣的是得到一个批次的结果要比避免工会。在这里你去:

set @last_key = null; 
set @seq = 1; 
select foreignkey, case when @last_key is null or @last_key != foreignkey then @seq := 1 else @seq := @seq + 1 end as sequence, code, @last_key := foreignkey as foo from (
    select foreignkey, code1 as code 
    from dataset 
    where code1 is not null 
    union 
    select foreignkey, code2 
    from dataset 
    where code2 is not null 
    union 
    select foreignkey, code3 
    from dataset 
    where code3 is not null 
    order by 1 
) foo; 
+0

+1,联盟真的是这里最好的方式。 – davidethell