Как разделить строку через запятую без использования цикла в хранимой процедуре - PullRequest
0 голосов
/ 21 ноября 2011

Как разделить строку через запятую без использования цикла

для примера: -

У меня есть строка, разделенная запятой, как 4,3,5,2,5,9

если я хочу получить строку после 3-й запятой без использования цикла.

Ответы [ 2 ]

1 голос
/ 21 ноября 2011
DECLARE @str varchar(MAX)='001,002,03,0004,05,6,07'
    ,@separator char(1)=','
    ,@n int = 3;

WITH str_nums ( id, n1, n2 ) 
AS 
( 
SELECT CAST(1 as int) as id, CAST(0 as bigint) as n1, CHARINDEX(@separator, @str+@separator) as n2
UNION ALL
SELECT id + 1, n2 as n1, CHARINDEX(@separator, @str+@separator, n2+1) as n2
FROM str_nums
WHERE n2<len(@str)
) 

SELECT SUBSTRING(@str, n1+1, n2-n1-1) as n_str
FROM str_nums
WHERE id = @n
GO
1 голос
/ 21 ноября 2011

Было бы полезно, если бы мы знали , почему вы не можете использовать цикл, но вы можете использовать пользовательскую функцию CLR (которая может использовать цикл за кулисами) или XQuery :

DECLARE @S varchar(max),
  @Split char(1),
  @X xml

SELECT @S = '1,2,3,4,5',
  @Split = ','

SELECT @X = CONVERT(xml,'<root><s>' + REPLACE(@S,@Split,'</s><s>') + '</s></root>')

SELECT [Value] = T.c.value('.','varchar(20)')
FROM @X.nodes('/root/s') T(c)

Затем, чтобы получить только третью (или любую другую порядковую строку), вы можете использовать решение на основе ROW_NUMBER, чтобы выбрать нужную вам строку.

РЕДАКТИРОВАТЬ: на основе вопроса в комментарии, вот решение для получения третьей строки.В некотором смысле вы должны подделать заказ ROW_NUMBER из-за того, что у вас нет наложенного заказа на основе данных.Обычно он не позволяет вам ORDER BY константу, но оператор CASE справляется с этим.Измените WHERE iq.Ordinal = 3 на то, что вы хотите получить желаемую строку:

DECLARE @S varchar(max),
  @Split char(1),
  @X xml

SELECT @S = '1,2,3,4,5',
  @Split = ','

SELECT @X = CONVERT(xml,'<root><s>' + REPLACE(@S,@Split,'</s><s>') + '</s></root>')

SELECT TOP 1 Value
FROM
(    
    SELECT [Value] = T.c.value('.','varchar(20)'), 
                ROW_NUMBER() OVER (ORDER BY 
                    CASE 
                        WHEN T.c.value('.', 'varchar(20)') = 0
                        THEN 0 
                        ELSE 0 
                    END ASC) AS Ordinal
    FROM @X.nodes('/root/s') T(c)
) iq
WHERE iq.Ordinal = 3
...