将多个分隔符分隔的字段视为不同的行
Treating multiple delimiter separated fields as distinct rows
我继承了一个 table(谁没有,对吧?),它的数据如下所示:
Item | Properties | Quantity
--------------------------------------------------------------------
Shirt | button-down,polo,sleeveless | 4,5,8
短期内,我想创建一个视图,但最终我想在时间允许的情况下将数据导出到 table 的新版本,并且更像是:
Item | Properties | Quantity
--------------------------------------------------------------------
Shirt | button-down | 4
Shirt | polo | 5
Shirt | sleeveless | 8
本质上,采取多个列组(我想会有其他 tables,其中有比两列更多的列,具有这种行为)已知是分隔符分隔并将它们分成不同的行?收集的任何其他不是这样的行将像本例中的 Item 一样在它们之间共享。 # of 逗号在这些类型之间是统一的。
编辑:我使用了 How to convert comma separated NVARCHAR to table records in SQL Server 2005? 的答案中给出的函数,这是我目前拥有的函数:
select distinct data.item, tmptbl.[String] from
data cross apply [ufn_CSVToTable](data.properties, ',') tmptbl ...
这适用于单列上下文,但将该函数完全应用于第二列(在本例中为数量)会生成所有可能的属性和数量组合,对吧?事实上,是的,当我尝试时它确实导致了那个结果。看来我需要一个游标或类似的东西来有效地分解成单独的属性行[i] | quantity[i],将尝试构建它。那或者可能只是 select 数据并在应用程序端拆分它。
CREATE FUNCTION [dbo].[ReturnTableOfVarchars]
(@IDList varchar(8000))
-- allow up to 256 varchar
RETURNS @IDTable table (RecordID varchar(256) NOT NULL)
AS
BEGIN
DECLARE @IDListPosition int,
@ArrValue varchar(8000)
SET @IDList = COALESCE(@IDList,'')
IF @IDList<>''
BEGIN
-- add a comma to end of list
SELECT @IDList = @IDList+','
-- Loop through the comma delimited string list
WHILE PATINDEX('%,%',@IDList)<>0
BEGIN
-- find the position of the first comma in the list
SELECT @IDListPosition = PATINDEX('%,%',@IDList)
-- extract the string
SELECT @ArrValue = LEFT(@IDList, @IDListPosition - 1)
INSERT @IDTable (RecordID) VALUES(@ArrValue)
-- remove processed string
SELECT @IDList = STUFF(@IDList,1,@IDListPosition ,'')
END
END
RETURN
END
使用:
declare @itemvalues varchar(100) ,@itemcount varchar(100)
set @itemvalues='button-down,polo,sleeveless'
SET @itemcount =' 4,5,8'
select * from dbo.ReturnTableOfVarchars(@itemvalues)
select * from dbo.ReturnTableOfVarchars(@itemcount)
上面的函数从字符串中拆分值,您可以插入 select 中的值或根据您的过程进行更新。
使用 here..
中的拆分字符串之一
如果您确定属性的数量始终与数量相同(我的意思是属性中有 3 个值,数量中有 3 个值),那么您可以将下面的连接替换为内部连接..
;With cte
as
(select t.item ,a1.item as 'Properties',row_number() over (order by (select null)) as rownum1
from #test t
cross apply
[dbo].[SplitStrings_Numbers](proper,',') a1
)
,cte1 as
(
select a2.item as quantity,row_number() over (order by (select null)) as rownum2
from #test t
cross apply
[dbo].[SplitStrings_Numbers](quantity,',') a2
)
Select c.ite,c.Properties,c1.quantity
from cte c
full join
cte1 c1
on c.rownum1=c1.rownum2
输出:
item Properties quantity
Shirt button-down 4
Shirt polo 5
Shirt sleeveless 8
借助拆分器和交叉应用
Declare @YourTable table (item varchar(50),Properties varchar(50),Quantities varchar(50))
Insert into @YourTable values
('Shirt','button-down,polo,sleeveless','4,5,8')
Select A.item
,B.Properties
,B.Quantities
From @YourTable A
Cross Apply (Select Properties=A.Key_Value
,Quantities=B.Key_Value
From (Select * from [dbo].[udf-Str-Parse](A.Properties,',')) A
Left Join (Select * from [dbo].[udf-Str-Parse](A.Quantities,',')) B on A.Key_PS=B.Key_PS
) B
Returns
item Properties Quantities
Shirt button-down 4
Shirt polo 5
Shirt sleeveless 8
UDF
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimeter varchar(10))
--Usage: Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
-- Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
-- Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|')
-- Select * from [dbo].[udf-Str-Parse]('hello world. It. is. . raining.today','.')
Returns @ReturnTable Table (Key_PS int IDENTITY(1,1), Key_Value varchar(max))
As
Begin
Declare @XML xml;Set @XML = Cast('<x>' + Replace(@String,@Delimeter,'</x><x>')+'</x>' as XML)
Insert Into @ReturnTable Select Key_Value = ltrim(rtrim(String.value('.', 'varchar(max)'))) FROM @XML.nodes('x') as T(String)
Return
End
我继承了一个 table(谁没有,对吧?),它的数据如下所示:
Item | Properties | Quantity
--------------------------------------------------------------------
Shirt | button-down,polo,sleeveless | 4,5,8
短期内,我想创建一个视图,但最终我想在时间允许的情况下将数据导出到 table 的新版本,并且更像是:
Item | Properties | Quantity
--------------------------------------------------------------------
Shirt | button-down | 4
Shirt | polo | 5
Shirt | sleeveless | 8
本质上,采取多个列组(我想会有其他 tables,其中有比两列更多的列,具有这种行为)已知是分隔符分隔并将它们分成不同的行?收集的任何其他不是这样的行将像本例中的 Item 一样在它们之间共享。 # of 逗号在这些类型之间是统一的。
编辑:我使用了 How to convert comma separated NVARCHAR to table records in SQL Server 2005? 的答案中给出的函数,这是我目前拥有的函数:
select distinct data.item, tmptbl.[String] from
data cross apply [ufn_CSVToTable](data.properties, ',') tmptbl ...
这适用于单列上下文,但将该函数完全应用于第二列(在本例中为数量)会生成所有可能的属性和数量组合,对吧?事实上,是的,当我尝试时它确实导致了那个结果。看来我需要一个游标或类似的东西来有效地分解成单独的属性行[i] | quantity[i],将尝试构建它。那或者可能只是 select 数据并在应用程序端拆分它。
CREATE FUNCTION [dbo].[ReturnTableOfVarchars]
(@IDList varchar(8000))
-- allow up to 256 varchar
RETURNS @IDTable table (RecordID varchar(256) NOT NULL)
AS
BEGIN
DECLARE @IDListPosition int,
@ArrValue varchar(8000)
SET @IDList = COALESCE(@IDList,'')
IF @IDList<>''
BEGIN
-- add a comma to end of list
SELECT @IDList = @IDList+','
-- Loop through the comma delimited string list
WHILE PATINDEX('%,%',@IDList)<>0
BEGIN
-- find the position of the first comma in the list
SELECT @IDListPosition = PATINDEX('%,%',@IDList)
-- extract the string
SELECT @ArrValue = LEFT(@IDList, @IDListPosition - 1)
INSERT @IDTable (RecordID) VALUES(@ArrValue)
-- remove processed string
SELECT @IDList = STUFF(@IDList,1,@IDListPosition ,'')
END
END
RETURN
END
使用:
declare @itemvalues varchar(100) ,@itemcount varchar(100)
set @itemvalues='button-down,polo,sleeveless'
SET @itemcount =' 4,5,8'
select * from dbo.ReturnTableOfVarchars(@itemvalues)
select * from dbo.ReturnTableOfVarchars(@itemcount)
上面的函数从字符串中拆分值,您可以插入 select 中的值或根据您的过程进行更新。
使用 here..
中的拆分字符串之一如果您确定属性的数量始终与数量相同(我的意思是属性中有 3 个值,数量中有 3 个值),那么您可以将下面的连接替换为内部连接..
;With cte
as
(select t.item ,a1.item as 'Properties',row_number() over (order by (select null)) as rownum1
from #test t
cross apply
[dbo].[SplitStrings_Numbers](proper,',') a1
)
,cte1 as
(
select a2.item as quantity,row_number() over (order by (select null)) as rownum2
from #test t
cross apply
[dbo].[SplitStrings_Numbers](quantity,',') a2
)
Select c.ite,c.Properties,c1.quantity
from cte c
full join
cte1 c1
on c.rownum1=c1.rownum2
输出:
item Properties quantity
Shirt button-down 4
Shirt polo 5
Shirt sleeveless 8
借助拆分器和交叉应用
Declare @YourTable table (item varchar(50),Properties varchar(50),Quantities varchar(50))
Insert into @YourTable values
('Shirt','button-down,polo,sleeveless','4,5,8')
Select A.item
,B.Properties
,B.Quantities
From @YourTable A
Cross Apply (Select Properties=A.Key_Value
,Quantities=B.Key_Value
From (Select * from [dbo].[udf-Str-Parse](A.Properties,',')) A
Left Join (Select * from [dbo].[udf-Str-Parse](A.Quantities,',')) B on A.Key_PS=B.Key_PS
) B
Returns
item Properties Quantities
Shirt button-down 4
Shirt polo 5
Shirt sleeveless 8
UDF
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimeter varchar(10))
--Usage: Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
-- Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
-- Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|')
-- Select * from [dbo].[udf-Str-Parse]('hello world. It. is. . raining.today','.')
Returns @ReturnTable Table (Key_PS int IDENTITY(1,1), Key_Value varchar(max))
As
Begin
Declare @XML xml;Set @XML = Cast('<x>' + Replace(@String,@Delimeter,'</x><x>')+'</x>' as XML)
Insert Into @ReturnTable Select Key_Value = ltrim(rtrim(String.value('.', 'varchar(max)'))) FROM @XML.nodes('x') as T(String)
Return
End