0

我有一个与在以下位置发布和回答的问题非常相似的问题:SQL 如何将一列拆分为多个变量列

就我而言,我有一列数据用两种分隔符分隔(我知道,很糟糕)。这是一些开始的代码:

create table #MessyDelim
(DelimList varchar(255));

insert into #MessyDelim
Values ('30;120;100')
, ('50;60')
, ('75/10')
, ('115/50/20/10/5')
, ('80;65;40;23;12;10')
, ('100')

我的目标是使用函数或 CTE 分别返回这些值。理想情况下,我希望它们在单独的列中返回(必须动态确定列数)。

这是所需的输出:

DL1  DL2  DL3  DL4  DL5  DL6
50   60
75   10
115  50   20   10   5 
80   65   40   23   12   10
100
4

2 回答 2

1

I love a good puzzle.

;WITH
MessyDelim AS --As Nenad Zivkovic suggested, standardize on one delimiter for simplicity
(   SELECT DelimList,REPLACE(DelimList,'/',';') AS String 
    FROM #MessyDelim),
Split AS --Recursive CTE to produce strings each with one less delimited value attached
(   SELECT DelimList, 1 AS Sort, String + ';' AS String
    FROM MessyDelim
    UNION ALL
    SELECT DelimList, Sort+1, RIGHT(String,LEN(String)-CHARINDEX(';',String))
    FROM Split
    WHERE CHARINDEX(';',String) > 0 ),
Cleanup AS --Reduce strings to single delimited value each
(   SELECT DelimList,LEFT(String,CHARINDEX(';',String)-1) AS String, Sort
    FROM Split
    WHERE String <> '' )    
SELECT DelimList, --Pivot out into columns
    [1] AS DL1,
    [2] AS DL2,
    [3] AS DL3,
    [4] AS DL4,
    [5] AS DL5,
    [6] AS DL6 
FROM Cleanup
PIVOT(MAX(String) FOR Sort IN ([1],[2],[3],[4],[5],[6])) pvt
ORDER BY DelimList
OPTION (MAXRECURSION 10) --Just for safety sake

SQL Fiddle

于 2013-10-10T14:48:48.217 回答
1

这里是动态生成列的完整动态 SQL。

;WITH
MessyDelim AS --As Nenad Zivkovic suggested, standardize on one delimiter for simplicity
(   SELECT DelimList,REPLACE(DelimList,'/',';') AS String 
    FROM #MessyDelim),
Split AS --Recursive CTE to produce strings each with one less delimited value attached
(   SELECT DelimList, 1 AS Sort, String + ';' AS String
    FROM MessyDelim
    UNION ALL
    SELECT DelimList, Sort+1, RIGHT(String,LEN(String)-CHARINDEX(';',String))
    FROM Split
    WHERE CHARINDEX(';',String) > 0 )

--Reduce strings to single delimited value each, and store in table
SELECT DelimList,LEFT(String,CHARINDEX(';',String)-1) AS String, Sort
INTO #CleanDelim
FROM Split
WHERE String <> ''
OPTION (MAXRECURSION 10)

--Produce dynamic list of column names and alias for SELECT list
DECLARE @Cols AS VARCHAR(MAX)
SELECT @Cols = STUFF((SELECT DISTINCT '],[' + CAST(Sort AS VARCHAR) + '] AS [DL' + CAST(Sort AS VARCHAR)
FROM #CleanDelim 
ORDER BY '],[' + CAST(Sort AS VARCHAR) + '] AS [DL' + CAST(Sort AS VARCHAR)
FOR XML PATH('')),1,2,'') + ']'

--Produce dynamic list of column names for PIVOT clause
DECLARE @List AS VARCHAR(MAX)
SELECT @List = STUFF((SELECT DISTINCT '],[' + CAST(Sort AS VARCHAR)
FROM #CleanDelim 
ORDER BY '],[' + CAST(Sort AS VARCHAR)
FOR XML PATH('')),1,2,'') + ']'

--Generate dynamic query
DECLARE @SQL AS VARCHAR(MAX)
SELECT @SQL = '
SELECT DelimList,' + @Cols + '
FROM #CleanDelim
PIVOT(MAX(String) FOR Sort IN (' + @list + ')) pvt'
FROM #CleanDelim

--Execute dynamic query
EXEC(@SQL)

SQL小提琴

于 2013-10-10T15:29:27.910 回答