SQL-将单个列拆分为多行

SQL-将单个列拆分为多行,sql,oracle,Sql,Oracle,我在数据库中有一个类似的记录(作为示例) 我需要导出数据并创建多个记录,其中Brand有多个条目。我还需要增加输出上的ID,这样就不会有重复项。(我可以为此使用序列,并将其设置为更高的最大值(以db为单位) 我的输出看起来像 ID, Name, Brand 1, Bike, Schwinn 2, Car, Ford Sequence.nextval, Car, Honda Sequence.nextval, Car, Chevy 3, Bike, Schwinn Sequence.nextval

我在数据库中有一个类似的记录(作为示例)

我需要导出数据并创建多个记录,其中Brand有多个条目。我还需要增加输出上的ID,这样就不会有重复项。(我可以为此使用序列,并将其设置为更高的最大值(以db为单位)

我的输出看起来像

ID, Name, Brand
1, Bike, Schwinn
2, Car, Ford
Sequence.nextval, Car, Honda
Sequence.nextval, Car, Chevy
3, Bike, Schwinn
Sequence.nextval, Bike, Trex
4, Car, Honda
我想尝试用
SQL
语句来解释这一点。基本上,我通过straight
SQL
将这些数据作为
csv
文件转储


我的困难是试图通过品牌栏
循环/拆分

您可以使用以下select语句:

with test_tab (ID, Name, Brand) as (
select 1, 'Bike', 'Schwinn' from dual union all
select 2, 'Car', 'Ford, Honda, Chevy' from dual union all
select 3, 'Bike', 'Schwinn, Trex' from dual union all
select 4, 'Car', 'Honda' from dual)
--------------------
-- End of Data Preparation
--------------------
select case when level <> 1 then <your_sequece>.nextval else id end as id, 
       name, 
       trim(regexp_substr(Brand, '[^,]+', 1, level)) BRAND
  from test_tab
connect by regexp_substr(Brand, '[^,]+', 1, level) is not null
    and prior Brand = Brand
    and prior sys_guid() is not null;
您可以将Insert语句编写为

Insert into <destination_table>
    select case when level <> 1 then <your_sequece>.nextval else id end as id, 
           name, 
           trim(regexp_substr(Brand, '[^,]+', 1, level)) BRAND
      from <source_table>
    connect by regexp_substr(Brand, '[^,]+', 1, level) is not null
        and prior Brand = Brand
        and prior sys_guid() is not null;

谢谢,桑,很棒的东西。不幸的是,它不能完全工作,因为我有重复品牌的记录,例如1,‘汽车’、‘福特、本田、雪佛兰’,记录2=2,‘卡车’、‘福特、本田、,雪佛兰“它似乎陷入了某种循环,我用
和previous ID=ID
替换了大量的recordsTry,因为它的ID在源数据中似乎是唯一的。我已经修改了答案。这类问题是一个完美的例子,说明了为什么逗号分隔字段是一个坏主意,而数据库规范化很重要。
ID      NAME    BRAND
---------------------
2   Car     Ford
5   Car     Honda
6   Car     Chevy
4   Car     Honda
1   Bike    Schwinn
3   Bike    Schwinn
7   Bike    Trex
Insert into <destination_table>
    select case when level <> 1 then <your_sequece>.nextval else id end as id, 
           name, 
           trim(regexp_substr(Brand, '[^,]+', 1, level)) BRAND
      from <source_table>
    connect by regexp_substr(Brand, '[^,]+', 1, level) is not null
        and prior Brand = Brand
        and prior sys_guid() is not null;
select case when level <> 1 then <your_sequece>.nextval else id end as id, 
       name, 
       trim(regexp_substr(Brand, '[^,]+', 1, level)) BRAND
  from <source_table>
connect BY regexp_substr(Brand, '[^,]+', 1, level) is not null
    and prior ID = ID
    and prior sys_guid() is not null;