SQL Server 2008 Разбить строковую переменную по номеру токена на строку - PullRequest
1 голос
/ 18 июня 2010

У меня довольно простое требование - у меня есть таблица со следующей (соответствующей) структурой.

with cte as(
select 1 id,'AA,AB,AC,AD' names union all
select 2,'BA,BB' union all
select 3,'CA,CB,CC,CD,CE' union all
select 4,'DA,DB,DC'
)

Я хотел бы создать оператор выбора, который будет разбивать каждый столбец «имен» на несколько строк.

Например, первая строка должна выдать

1,'AA'
1,'AB'
1,'AC'
1,'AD'

Можем ли мы сделать это, используя только SQL. Это легко сделать в Oracle.

Ответы [ 2 ]

2 голосов
/ 18 июня 2010

Вы можете сделать это в одном запросе без пользовательских функций, если используете XML:

WITH cte AS( /*your data*/
    SELECT 1 id,'AA,AB,AC,AD' names UNION ALL
    SELECT 2,'BA,BB' UNION ALL
    SELECT 3,'CA,CB,CC,CD,CE' UNION ALL
    SELECT 4,'DA,DB,DC'
)
, xmlData AS ( /*make into xml*/
    SELECT id, cast('<root><x>'+replace(names,',','</x><x>')+'</x></root>' as xml) AS theXML
    FROM cte
)
SELECT id, x.value('.','varchar(100)')  /*split up*/
FROM xmlData
CROSS APPLY  xmlData.theXML.nodes('//x') AS func(x)
1 голос
/ 18 июня 2010

Вы можете создать функцию разделения, которая возвращает таблицу, а затем выбрать из этой таблицы.

/***************************************************************************
 **
 ** Function: split
 ** In: @ipRowData - The delimited list of items to split.
 ** In: @ipSplitOn - The delimiter which separates the items in @rowData.
 ** Returns: A table object containing the split items. The table object
 **    will have an ID and Data column, where ID is the number of the item
 **    in the original list and Data is the value of the item.
 **
 ** Description:
 **    Splits a delimited set of items and returns them
 **    as a table object.
 ***************************************************************************/
CREATE FUNCTION [dbo].[split]
(
   @ipRowData NVARCHAR(4000),
   @ipSplitOn NVARCHAR(5)
)
RETURNS @rtnValue table
(
   ID INT identity(1,1),
   Data NVARCHAR(100)
)
AS
BEGIN
   DECLARE
      @cnt INT
      Set @cnt = 1

   WHILE (Charindex(@ipSplitOn,@ipRowData)>0)
   BEGIN
      INSERT INTO @rtnValue
                ( data )
                  SELECT Data = ltrim(rtrim(Substring(@ipRowData,1,Charindex(@ipSplitOn,@ipRowData)-1)))
      SET @ipRowData = Substring(@ipRowData,Charindex(@ipSplitOn,@ipRowData)+1,len(@ipRowData))
      SET @cnt = @cnt + 1
   END

   INSERT INTO @rtnValue (data)
   SELECT DATA = ltrim(rtrim(@ipRowData))

   RETURN
END

GO

Пример использования:

select 1,data from [dbo].split('AA,AB,AC,AD', ',');

Выход:

(No column name)   data
1                  AA
1                  AB
1                  AC
1                  AD
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...