【问题标题】:Problem in string concatenation in sql server using FOR XML Path.使用 FOR XML 路径的 sql server 中的字符串连接问题。
【发布时间】:2011-09-16 04:10:52
【问题描述】:

我有以下数据

UniqueID    ID  data
1       1   a
2       1   2
3       1   b
4       1   1
5       2   d
6       2   3
7       2   r

预期的输出是

ID  ConcatData
1   a,-,-,b,-
2   d,-,-,-,r

我们要做的是,数字字符的数量必须用那些破折号('-')替换,然后我们需要合并相应 id 的数据。

到目前为止,我正在使用以下查询

declare @t table(UniqueID int identity(1,1), ID int, data varchar(10))  
insert into @t select 1, 'a' union all  select 1, '2' union all select 1, 'b' 
union all select 1, '1' union all select 2, 'd' union all select 2, '3' 
union all select 2, 'r' 

select * from @t

;with cte1 as 
(     
    select 
        UniqueId
        , id
        , data
        , case when isnumeric(data) = 1 then cast(data as int) end Level
         from @t     
    union all     
    select 
        UniqueId
        , id
        , CAST('-' as varchar(10))
        , Level - 1     
    from cte1     
    where Level > 0 ) 
,cte2 as
(
select id, GroupID = Dense_Rank() Over(Order by id),data, DataOrder = ROW_NUMBER() over(order by UniqueID, Level)
from cte1 
where Level is null or data = '-' 
) 

SELECT
ID
, (select data + ',' 
from cte2 t2 
where t2.GroupID = t1.GroupID
for XML path('')
) as ConcatData
from cte2 t1
group by t1.ID ,t1.GroupID

但是输出是

ID  ConcatData
1   a,b,-,-,-,
2   d,r,-,-,-,

也就是说,我无法在字符之间放置破折号('-')。

请帮忙

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql common-table-expression


    【解决方案1】:

    试试这个:

    ;with cte1 as
    (
    select 
    UniqueId
    , id
    , data
    ,case when isnumeric(data) = 1 
        THEN replicate(',-',data) 
        ELSE ',' + data end as string
    from @t
    )
    
    select 
    id
    ,LTRIM(STUFF(
        (
        SELECT
          ' ' + t2.String
        FROM Cte1 t2
        WHERE t2.id = t1.id
        FOR XML PATH('')
        ), 2, 1, ''
      )) As concatenated_string
    from cte1 t1 group by t1.ID ,t1.ID 
    

    适用于上面的示例数据,可能比使用游标快一点

    【讨论】:

    • 感谢学习有关复制的新知识。我同意,你的建议更好。谢谢:)
    【解决方案2】:

    下面是创建表

    Create table #temp
    (
        IDUnique int Identity(1,1),
        ID int, 
        data varchar(100)
    )
    

    以下是您建议的记录。

    Insert into #temp(ID, data) Values(1, 'a')
    Insert into #temp(ID, data) Values(1, '2')
    Insert into #temp(ID, data) Values(1, 'b')
    Insert into #temp(ID, data) Values(1, '1')
    Insert into #temp(ID, data) Values(2, 'd')
    Insert into #temp(ID, data) Values(2, '3')
    Insert into #temp(ID, data) Values(2, 'r')
    

    以下是游标实现

    declare @IDUnique int
    declare @ID int
    declare  @data varchar(100)
    declare @Latest int
    declare @Previous int
    declare @Row int
    
    set @Latest = 1
    set @Previous = 1
    
    Create Table #temp1
    (
        ID int,
        data varchar(100)
    )
    
    --SELECT Row_Number() Over(Order by IDUnique) Row, IDUnique, ID, data  From #temp
    
    
    DECLARE @getAccountID CURSOR SET @getAccountID = CURSOR FOR SELECT Row_Number() Over(Order by IDUnique) Row, IDUnique, ID, data  From #temp
    OPEN @getAccountID
    FETCH NEXT FROM @getAccountID INTO @Row, @IDUnique, @ID, @data
    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF(@Row = 1)
        Begin
            Set @Previous = @ID
            Set @Latest = @ID
            Insert into #temp1(ID, data)values(@Previous, @data)
        End
        Else If (@Previous <> @ID)
        Begin
            Set @Previous = @ID
            Set @Latest = @ID
            Insert into #temp1(ID, data)values(@Previous, @data)
        End
        Else
        Begin
            Declare @number int
            if(ISNUMERIC(@data) = 1)
            Begin
                Set @number = Convert(int , @data)
                While(@number <> 0)
                Begin
                    Update #temp1 Set Data  = Data + ',-' Where ID = @ID
                    Set @number = @number - 1
                End
            End
            Else    
            begin
                Update #temp1 Set Data  = Data + ',' + @data Where ID = @ID
            End
        End
    
        FETCH NEXT FROM @getAccountID INTO @Row, @IDUnique, @ID, @data
    END
    CLOSE @getAccountID
    DEALLOCATE @getAccountID
    
    Select * from #temp1
    Select * from #temp
    Drop Table #temp
    

    这是最终结果集

    【讨论】:

    • 您正在过滤数值和其他数值。这就是输出不正确的原因。为了按顺序移动,我认为你应该使用光标移动..
    猜你喜欢
    • 2012-12-14
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多