sql-server - 动态地将列拆分/分隔为多个列垂直使用sql server

标签 sql-server split sql-server-2012

我需要拆分一个 ID 字段重复多次的表。分号将用作分隔符。这是一个动态数据集,其中“构建”列是动态的。构建者拥有多年的动态经验,因此我们不能使用固定位置分隔符。这是示例数据。

---- Sample data
    CREATE TABLE TEST1
    (
        ID varchar(20), 
        FIELD varchar(max)
    );

    INSERT INTO TEST1 (ID, FIELD)
    VALUES 
    ('ERIC','BUILT;1995/PROPERTY;House/TYPE;OZ C1/BUILT;2010/PROPERTY;Condo/TYPE;F4/BUILT;2010/PROPERTY;Condo/TYPE;F9/'),
    ('ERIC','BUILT;1996/PROPERTY;House/TYPE;OZ C1/'),
    ('ERIC','BUILT;1997/PROPERTY;House/TYPE;OZ C1/'),
    ('ERIC','BUILT;2011/PROPERTY;Condo/TYPE;F4/BUILT;2015/PROPERTY;House/TYPE;C5/');

这是我想要的最终结果,其中 ID、内置、属性和类型作为列标题和垂直显示的数据。

ID      BUILT   PROPERTY    TYPE
--------------------------------
ERIC    1995    House       OZ C1
ERIC    2010    Condo       F4
ERIC    2010    Condo       F9
ERIC    1996    House       OZ C1
ERIC    1997    House       OZ C1
ERIC    2011    Condo       F4
ERIC    2015    House       C5

我知道以下分割列的方法。然而这不是我所要求的。这将水平分割数据,而我需要垂直分割数据。

WITH Split_Fields (ID, xmlfields)
AS
(
    SELECT ID ,
    CONVERT(XML,'<Fields><field>'  
    + REPLACE(name,'.', '</field><field>') + '</field></Fields>') AS xmlfields
      FROM TEST1
)

SELECT ID      
 ,xmlfields.value('/Fields[1]/field[1]';'varchar(100)') AS Field1    
 ,xmlfields.value('/Fields[1]/field[2]';'varchar(100)') AS Field2
,xmlfields.value('/Fields[1]/field[3]';'varchar(100)') AS Field3    
 ,xmlfields.value('/Fields[1]/field[4]';'varchar(100)') AS Field4
,xmlfields.value('/Fields[1]/field[5]';'varchar(100)') AS Field5
FROM Split_Fields

我已经浏览过SO,但找不到任何关于按照我需要的方式分割数据的内容。请有人帮我解决这个问题。我真的很困惑。

我已成功添加“|”作为分隔符来指定新行的开始位置,如 Sean 所建议的那样。恐怕我掌握的数据有限,无法做更多的事情。这是新的示例数据。

---- Sample data
    CREATE TABLE TEST1
    (
        ID varchar(20), 
        FIELD varchar(max)
    );

    INSERT INTO TEST1 (ID, FIELD)
    VALUES 
    ('ERIC','BUILT;1995/PROPERTY;House/TYPE;OZ C1|BUILT;2010/PROPERTY;Condo/TYPE;F4|BUILT;2010/PROPERTY;Condo/TYPE;F9|'),
    ('ERIC','BUILT;1996/PROPERTY;House/TYPE;OZ C1|'),
    ('ERIC','BUILT;1997/PROPERTY;House/TYPE;OZ C1|'),
    ('ERIC','BUILT;2011/PROPERTY;Condo/TYPE;F4|BUILT;2015/PROPERTY;House/TYPE;C5|');

西姆兰

最佳答案

借助一个(或两个)CROSS APPLY 和一点 XML

示例

Select A.ID
      ,Built    = C.Pos1
      ,Property = C.Pos3
      ,PropType = C.Pos5
 From  Test1 A
 Cross Apply (
                Select RetSeq = Row_Number() over (Order By (Select null))
                      ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                From  (Select x = Cast('<x>' + replace((Select replace(A.FIELD,'BUILT;','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
                Cross Apply x.nodes('x') AS B(i)
                Where B.i.value('(./text())[1]', 'varchar(max)') is not null
             ) B
 Cross Apply (
                Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
                      ,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
                      ,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
                From  (Select Cast('<x>' + replace((Select replace(replace(B.RetVal,'/',';'),';','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A 
             ) C

返回

ID      Built   Property    PropType
ERIC    1995    House       OZ C1
ERIC    1996    House       OZ C1
ERIC    1997    House       OZ C1
ERIC    2010    Condo       F4
ERIC    2010    Condo       F9
ERIC    2011    Condo       F4
ERIC    2015    House       C5

关于sql-server - 动态地将列拆分/分隔为多个列垂直使用sql server,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51194713/

相关文章:

sql - 货币列的货币、小数或数字

sql-server - 从 SQL Server 表中选择所有记录都具有指定范围的列值

r - 如何根据以某个前缀开头的一列名称值将数据帧拆分为不同的数据帧?

python - 我如何将字符串分成 python 部分

sql-server - 如何在 SQL Server 中的特定字符后分割字符串并将该值更新到特定列

c# - 为什么 SQL Server 2008 及更高版本不支持派生自泛型的 CLR 类型?

sql - 在 SQL Server 中将垂直书写的单词转为水平书写的单词

sql-server - 如何在 Microsoft SQL 中查找具有特定列名的主键的表?

sql-server - 使用 Case 或 Join 的 TSQL Select 语句

sql-server - 多次选择一组行