【问题标题】:Fold in T-SQL?折叠 T-SQL?
【发布时间】:2008-11-10 21:40:09
【问题描述】:

如果我有以下格式的数据

 id    subid      text
 1     1          Hello
 1     2          World
 1     3          !
 2     1          B
 2     2          B
 2     3          Q

并希望采用这种格式:

 id  fold
 1   HelloWorld!
 2   BBQ

如何在 T-SQL 中完成它?

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    我强烈建议不要这样做。这就是你的应用层应该处理的事情。

    但是...如果您必须这样做:
    Concatenating Row Values in Transact-SQL

    【讨论】:

    • 哇,这些例子太激烈了。
    • 我不确定你所说的强烈是什么意思。
    • 看起来非常投入和抽象。
    • 同意。但是,这就是为什么我建议不要在 T-SQL 中执行它并在应用程序层中处理它。
    【解决方案2】:

    一个临时表和一个光标跃入脑海......

    亲爱的投票者:临时表和游标必须至少与上面接受的递归查询和自定义函数解决方案一样有效。克服对游标的恐惧,有时它们是最有效的解决方案。有时它们是唯一的解决方案。处理它。

    编辑:下面基于光标的解决方案。请注意,它没有其他地方提出的非光标(并且更复杂)解决方案的限制,并且性能可能大致相同(当然很难从六行表中分辨出来)。

    请不要仅仅因为某些博主说“这很糟糕”而放弃了 sql 的主要 for-each 构造;使用你自己的判断和一些常识。我尽可能避免使用游标,但不会到解决方案不可靠的地步。

    --initial data table
    create table #tmp (
        id int,
        subid int,
        txt varchar(256)
    )
    
    --populate with sample data from original question
    insert into #tmp (id,subid,txt) values (1, 1, 'Hello')
    insert into #tmp (id,subid,txt) values (1, 2, 'World')
    insert into #tmp (id,subid,txt) values (1, 3, '!')
    insert into #tmp (id,subid,txt) values (2, 1, 'B')
    insert into #tmp (id,subid,txt) values (2, 2, 'B')
    insert into #tmp (id,subid,txt) values (2, 3, 'Q')
    
    --temp table for grouping results
    create table #tmpgrp (
        id int,
        txt varchar(4000)
    )
    
    --cursor for looping through data
    declare cur cursor local for
        select id, subid, txt from #tmp order by id, subid
    
    declare @id int
    declare @subid int
    declare @txt varchar(256)
    
    declare @curid int
    declare @curtxt varchar(4000)
    
    
    open cur
    
    fetch next from cur into @id, @subid, @txt
    
    set @curid = @id
    set @curtxt = ''
    
    while @@FETCH_STATUS = 0 begin
        if @curid <> @id begin
            insert into #tmpgrp (id,txt) values (@curid,@curtxt)
            set @curid = @id
            set @curtxt = ''
        end
        set @curtxt = @curtxt + isnull(@txt,'')
        fetch next from cur into @id, @subid, @txt
    end
    
    insert into #tmpgrp (id,txt) values (@curid,@curtxt)
    
    close cur
    
    deallocate cur
    
    --show output
    select * from #tmpgrp
    
    --drop temp tables
    drop table #tmp
    drop table #tmpgrp
    

    【讨论】:

    • @[StingyJack]:除非它们是唯一有效的解决方案
    • @StingyJack:光标肯定有自己的位置。然而,正如所有人都提到的,这不是地方。
    • @StingyJack: 添加游标解决方案
    • @[Jason Lepack]: 添加游标解决方案
    • @AviewAnew:有时没有像老学校那样的学校,请参阅编辑
    【解决方案3】:
    declare  @tmp table (id int, subid int,txt varchar(256) )  
    --populate with sample data from original question 
    insert into @tmp (id,subid,txt) values (1, 1, 'Hello') 
    insert into @tmp (id,subid,txt) values (1, 2, 'World') 
    insert into @tmp (id,subid,txt) values (1, 3, '!') 
    insert into @tmp (id,subid,txt) values (2, 1, 'B') 
    insert into @tmp (id,subid,txt) values (2, 2, 'B') 
    insert into @tmp (id,subid,txt) values (2, 3, 'Q') 
    

    解决方案

    Select id, fold = (Select cast(txt as varchar(100)) from @tmp t2 where t1.id = t2.id for xml path(''))
    from @tmp t1
    group by t1.id
    

    【讨论】:

      【解决方案4】:

      将此包装在一个函数中以进行单次执行...

      DECLARE @returnValue varchar(4000)
      
      SELECT @returnValue = ISNULL(@returnValue + ', ' +  myTable.text, myTable.text)
      FROM myTable 
      
      RETURN @returnValue
      

      对于少量记录,这将起作用...对于 SQL 函数来说,超过 5 或 10 条记录太多了,需要按照其他人的建议将其移动到应用层。

      【讨论】:

        猜你喜欢
        • 2018-04-26
        • 2018-11-20
        • 2014-05-22
        • 2016-10-26
        • 2021-01-20
        • 2017-03-10
        • 2011-07-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多