Tsql 将多个分隔符分隔的字段视为不同的行

Tsql 将多个分隔符分隔的字段视为不同的行,tsql,sql-server-2005,Tsql,Sql Server 2005,我继承了一张没有的桌子,对吧?其数据如下所示: Item | Properties | Quantity -------------------------------------------------------------------- Shirt | button-down,polo,sleeveless | 4,5,8 短期而言,我希望创建一个视图,但最终我希望在时间允许的情况

我继承了一张没有的桌子,对吧?其数据如下所示:

Item          |             Properties        |        Quantity
--------------------------------------------------------------------
Shirt         |  button-down,polo,sleeveless  |          4,5,8
短期而言,我希望创建一个视图,但最终我希望在时间允许的情况下将数据导出到表的新版本,并使其更像:

Item          |             Properties        |        Quantity
--------------------------------------------------------------------
Shirt         |            button-down        |            4   
Shirt         |               polo            |            5
Shirt         |             sleeveless        |            8
从本质上讲,以多个列组为例,我想会有其他表,其中具有这种行为的列多于两个,这些表被分隔符分隔,并将它们分成不同的行?收集到的任何其他行与此不同,将在它们之间共享,就像本例中的项一样。这些类型之间逗号的数量是一致的

编辑:我使用了答案中给出的功能,这是我目前拥有的功能:

select distinct data.item, tmptbl.[String] from
  data cross apply [ufn_CSVToTable](data.properties, ',') tmptbl ...
这在单列上下文中有效,但将该函数直接应用于第二列数量将生成属性和数量的所有可能组合,对吗?事实上,是的,当我尝试时,它确实导致了这一点。看起来我需要一个游标或类似的东西来有效地分解成单独的属性行[I]|数量[I],我将尝试构造它。也可能只是选择数据,然后在应用程序端拆分数据

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  
上面的函数从字符串中分割值,您可以根据自己的过程插入选择或更新中的值


上面的函数从字符串中分割值,您可以根据您的过程插入选择或更新中的值。

使用从中分割的字符串之一

如果您确定属性的计数数始终与数量相同,我的意思是属性中有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
输出:


使用…中的一个拆分字符串

如果您确定属性的计数数始终与数量相同,我的意思是属性中有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
输出:


借助拆分器和交叉应用

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
返回

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

借助拆分器和交叉应用

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
返回

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

教授SQL的课程刚刚结束。在过去的几分钟里,我看到了许多关于sql/tsql的未定义问题,其中没有一个显示了他们自己试图解决的代码。请包括你自己尝试过的,遇到问题的地方,以及一个准确的问题,否则你的问题无法回答。好的,谢谢。将更新为包含,尽管它只允许以这种方式断开单个列。您是在使用SQL Server 2005,还是只是顺便提一下?使用适当的软件MySQL、Oracle、DB2等标记数据库问题是很有帮助的。。。和版本,例如sql-server-2014。语法和特性的差异往往会影响答案。教授SQL的课程刚刚结束。在过去的几分钟里,我看到了许多关于sql/tsql的未定义问题,其中没有一个显示了他们自己试图解决的代码。请包括你自己尝试过的,遇到问题的地方,以及一个准确的问题,否则你的问题无法回答。好的,谢谢。将更新为包含,尽管它只允许以这种方式断开单个列。您是在使用SQL Server 2005,还是只是顺便提一下?使用适当的软件MySQL、Oracle、DB2等标记数据库问题是很有帮助的。。。和版本,例如sql-server-2014。语法和功能的差异通常会影响答案。这似乎与CSVToTable函数的处理方式类似。有没有一种方法可以将这些功能连接起来,使button down | 4、polo | 5等等?这似乎与CSVToTable函数的处理方式类似。有没有一种方法可以将这些元素连接起来,比如按下按钮4、翻领5等等?啊,这是一种非常新颖的方法:单独拆分,在行号上连接。这是一种非常新颖的方法:单独拆分,合并行数。我会试一试的。