【问题标题】:Split values over multiple rows [duplicate]在多行上拆分值[重复]
【发布时间】:2012-10-21 00:06:30
【问题描述】:

可能重复:
Turning a Comma Separated string into individual rows

我有一个存储过程的以下输出,我想知道将值拆分为多行的最佳方法。

reference   name                            subjects       subjectstitle
LL9X81MT    Making and Decorating Pottery   F06,F27,F38       NULL

我需要修剪逗号处的主题字段并将信息复制到三行,以便数据如下。

reference   name                            subjects       subjectstitle
LL9X81MT    Making and Decorating Pottery   F06       NULL
LL9X81MT    Making and Decorating Pottery   F27       NULL
LL9X81MT    Making and Decorating Pottery   F38       NULL

我正在使用 MS SQL Server 2008 来设置这些 SP,只需要一些关于如何拆分主题字段的帮助。

谢谢,

【问题讨论】:

  • 数据如何进入该格式?一开始就不能正常退货吗?
  • 简单用这个:select refrence, sbj from TableX LATERAL VIEW explode(split(subjects, '[,]')) subjectTable AS sbj;

标签: sql sql-server sql-server-2008 stored-procedures


【解决方案1】:

您将需要使用类似于此的某种表值拆分函数:

create FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))       
returns @temptable TABLE (items varchar(MAX))       
as       
begin      
    declare @idx int       
    declare @slice varchar(8000)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx)       
        if len(@String) = 0 break       
    end   
return 
end;

然后您可以使用outer apply 加入您的表格:

select t1.reference,
  t1.name,
  t1.subjectstitle,
  i.items subjects
from yourtable t1
outer apply dbo.split(t1.subjects, ',') i

给出这样的结果:

| REFERENCE |                          NAME | SUBJECTSTITLE | SUBJECTS |
------------------------------------------------------------------------
|  LL9X81MT | Making and Decorating Pottery |        (null) |      F06 |
|  LL9X81MT | Making and Decorating Pottery |        (null) |      F27 |
|  LL9X81MT | Making and Decorating Pottery |        (null) |      F38 |

SQL fiddle with Demo

如果您想在没有拆分功能的情况下执行此操作,则可以使用 CTE:

;with cte (reference, name, subjectstitle, subjectitem, subjects) as
(
  select reference,
    name,
    subjectstitle,
    cast(left(subjects, charindex(',',subjects+',')-1) as varchar(50)) subjectitem,
         stuff(subjects, 1, charindex(',',subjects+','), '') subjects
  from yourtable
  union all
  select reference,
    name,
    subjectstitle,
    cast(left(subjects, charindex(',',subjects+',')-1) as varchar(50)) ,
    stuff(subjects, 1, charindex(',',subjects+','), '') subjects
  from cte
  where subjects > ''
) 
select reference, name, subjectstitle, subjectitem
from cte

SQL Fiddle with Demo

【讨论】:

  • +1 : 你可能更适合OUTER APPLY,以防万一......
  • @Dems 你可能是对的,更新感谢您的更正。
  • 在这个博拉德上已经有一个关于这个的话题,看起来在那里解决了stackoverflow.com/questions/5493510/…
  • @Jester - 您应该将问题标记为重复。这是你应该做的
  • 这些天在 SO 上回答了这么多重复的问题
【解决方案2】:

这将在没有拆分功能的情况下完成

SELECT T1.reference, T1.name, T2.my_Splits AS subjects, T1.subtitile
FROM
 (
  SELECT *,
  CAST('<X>'+replace(T.subjects,',','</X><X>')+'</X>' as XML) as my_Xml 
  FROM [yourTable] T
 ) T1
 CROSS APPLY
 ( 
 SELECT my_Data.D.value('.','varchar(50)') as my_Splits
 FROM T1.my_Xml.nodes('X') as my_Data(D)
 ) T2

【讨论】:

  • 非常好。效果很好。
  • 这很棒。有没有办法同时添加一个序列号来与拆分值一起使用?
  • 我想明白了。在 T2 中的“my_splits”正上方添加一个附加列:row_number() over (order by my_data.D) as sequence_num,
  • 性能更高。我从 1700 次读取到 28 次。制定了一个丑陋的执行计划,但我不在乎!
猜你喜欢
  • 2017-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 2020-09-24
  • 2015-07-07
  • 2016-08-09
  • 2015-07-28
相关资源
最近更新 更多