我需要拆分一个 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/