В SQL Server, как создать цикл while в select

данные будут такими:

    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, потому что он слишком медленный, у меня много данных. У кого-то есть хорошая идея? Возможно ли это?

Ответ 1

  • Создать функцию, которая анализирует входящую строку (скажем, "AABBCC" ) как таблицу строк (в частности, "AA", "BB", "CC" ).
  • Выберите идентификаторы из своей таблицы и используйте CROSS APPLY функцию с данными как аргумент, чтобы у вас было столько строк, сколько значений, содержащихся в текущие данные строки. Нет необходимости в курсорах или сохраненных процедурах.

Ответ 2

Ты мог бы сделать что-то вроде этого.....
Таблица

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

DROP TABLE #Temp
DROP TABLE #DestinationTable

Ответ 3

Нет функций, никаких курсоров. Попробуйте это

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

Ответ 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;