【问题标题】:In SQL Server, how to create while loop in select在 SQL Server 中,如何在 select 中创建 while 循环
【发布时间】:2016-08-11 18:35:30
【问题描述】:

数据会是这样的:

    id  |  data
    ----|---------
    1   |  AABBCC
    2   |  FFDD
    3   |  TTHHJJKKLL

我想要的结果是什么

    id  |  data
    ----|---------
    1   |  AA
    1   |  BB
    1   |  CC
    2   |  FF
    2   |  DD
    3   |  TT
    3   |  HH
    3   |  JJ
    3   |  KK
    3   |  LL 

我有一个使用光标的 sql 代码

DECLARE @table2 table ( id INTEGER, data VARCHAR(500))

DECLARE Cur CURSOR FOR
SELECT id FROM table1

OPEN Cur 

WHILE ( @@FETCH_STATUS = 0 )
    BEGIN
        DECLARE @LoopNum INTEGER
        DECLARE @tempID INTEGER
        DECLARE @tempDATA VARCHAR(255)
        FETCH NEXT FROM Cur INTO @tempID
        SET @tempDATA = SELECT data from table1 where id = @teampID
        SET @LoopNUM = 0
        WHILE @LoopNum< len(@tempDATA) / 2
            BEGIN
            INSERT INTO table2 (id, data)
            VALUES( @tempID, SUBSTRING(@tempDATA, @LoopNum * 2 +1, 2))
            SET @LoopNum = @LoopNum + 1
        END
    END

CLOSE Cur 
DEALLOCATE Cur 

SELECT * FROM table2

我不想使用 CURSOR,因为它太慢了,我有很多数据。 有人对此有好主意吗?有可能吗?

【问题讨论】:

    标签: sql sql-server sql-server-2008 tsql


    【解决方案1】:

    你可以这样做.....
    你的桌子

    CREATE TABLE TestTable 
    (
    ID INT,
    Data NVARCHAR(50)
    )
    GO
    
    INSERT INTO TestTable
    VALUES (1,'AABBCC'),
           (2,'FFDD'),
           (3,'TTHHJJKKLL')
    GO
    
    SELECT * FROM TestTable
    

    我的建议

    CREATE TABLE #DestinationTable
    (
    ID INT,
    Data NVARCHAR(50)
    )
    GO  
        SELECT * INTO #Temp FROM TestTable
    
        DECLARE @String NVARCHAR(2)
        DECLARE @Data NVARCHAR(50)
        DECLARE @ID INT
    
        WHILE EXISTS (SELECT * FROM #Temp)
         BEGIN 
            SELECT TOP 1 @Data =  DATA, @ID = ID FROM  #Temp
    
              WHILE LEN(@Data) > 0
                BEGIN
                    SET @String = LEFT(@Data, 2)
    
                    INSERT INTO #DestinationTable (ID, Data)
                    VALUES (@ID, @String)
    
                    SET @Data = RIGHT(@Data, LEN(@Data) -2)
                END
            DELETE FROM #Temp WHERE ID = @ID
         END
    
    
    SELECT * FROM #DestinationTable
    

    结果集

    ID  Data
    1   AA
    1   BB
    1   CC
    2   FF
    2   DD
    3   TT
    3   HH
    3   JJ
    3   KK
    3   LL
    

    删除临时表

    DROP TABLE #Temp
    DROP TABLE #DestinationTable
    

    【讨论】:

      【解决方案2】:

      没有函数,没有光标。试试这个

      with cte as(
      select CHAR(65) chr, 65 i 
      union all
      select CHAR(i+1) chr, i=i+1 from cte
      where CHAR(i) <'Z'
      )
      select * from(
      SELECT id, Case when LEN(data)>len(REPLACE(data, chr,'')) then chr+chr end data 
      FROM table1, cte) x
      where Data is not null
      

      【讨论】:

      • 我想测试一下,所以我建立了一个SQLFiddle
      • +1 没有测试这个,但是 CTE 也是这个任务的一个不错的选择。
      【解决方案3】:
      1. 创建将传入字符串(例如“AABBCC”)解析为字符串表(特别是“AA”、“BB”、“CC”)的函数。
      2. 从您的表中选择 ID 并使用带有 data 作为参数的函数CROSS APPLY,这样您将拥有与当前行的data 中包含的值一样多的行。不需要游标或存储过程。

      【讨论】:

        【解决方案4】:
        INSERT INTO Table2 SELECT DISTINCT ID,Data = STUFF((SELECT ', ' + AA.Data FROM Table1 AS AA WHERE AA.ID = BB.ID FOR XML PATH(''), TYPE).value('.','nvarchar(max)'), 1, 2, '') FROM Table1 AS BB 
        GROUP BY ID,Data
        ORDER BY ID;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-31
          • 2013-08-18
          • 2011-01-28
          • 2011-05-28
          • 2020-03-01
          • 2011-03-05
          • 2016-09-13
          • 2016-10-11
          相关资源
          最近更新 更多