ID SN Types
1 123 ABC,XYZ,TEST, RJK,CDF,TTT,UMB,UVX
2 234 RJK,CDF,TTT,UMB,UVX,TTT,UMB,UVX
3 345 OID,XYZ,TTT,UMB,UVX,TTT,UMB,UVX
作为
ID SN Types1 Types2 Types3 Types4 Types5 Types6 Types7 Types8
1 123 ABC XYZ TEST RJK CDF TTT UMB UVX
2 234 RJK CDF TTT UMB UVX TTT UMB UVX
3 345 OID XYZ TTT UMB UVX TTT UMB UVX
请发给我sqlcode 感谢,
答案 0 :(得分:2)
首先,创建一个维护顺序的拆分功能:
CREATE FUNCTION [dbo].[SplitStrings_Ordered]
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
AS
RETURN (SELECT [Index] = ROW_NUMBER() OVER (ORDER BY Number), Item
FROM (SELECT Number, Item = SUBSTRING(@List, Number,
CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number)
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects) AS n(Number)
WHERE Number <= CONVERT(INT, LEN(@List))
AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter)) = @Delimiter
) AS y);
现在,您可以将此功能与PIVOT
结合使用。这是一个自我封闭的示例,但您可以将最后一个查询中的@d
替换为您的真实表格。
DECLARE @d TABLE(ID INT, SN INT, Types NVARCHAR(MAX));
INSERT @d VALUES
(1,123,N'ABC,XYZ,TEST, RJK,CDF,TTT,UMB,UVX'),
(2,234,N'RJK,CDF,TTT,UMB,UVX,TTT,UMB,UVX' ),
(3,345,N'OID,XYZ,TTT,UMB,UVX,TTT,UMB,UVX' );
SELECT ID,SN,
Types1 = [1], Types2 = [2], Types3 = [3], Types4 = [4],
Types1 = [5], Types6 = [6], Types7 = [7], Types8 = [8]
FROM @d AS d CROSS APPLY dbo.SplitStrings_Ordered(d.Types, ',') AS y
PIVOT (MAX(Item) FOR [Index] IN ([1],[2],[3],[4],[5],[6],[7],[8])) AS p;
答案 1 :(得分:0)
T-SQL不适合处理以逗号分隔的值。但是,通过创造性地使用Recursive CTE,可以毫不费力地拆分列。以下查询假设原始数据中一行中总共不超过8种类型 - 可以简单地扩展以处理任意数量的类型(尽管不是动态的,必须知道最大数量):
;with TypesSplit as (
select [ID], [SN], 1 as [Index],
case when CHARINDEX(',', [Types]) <> 0 then substring([Types], CHARINDEX(',', [Types])+1, 1000) else '' end as [Types],
case when CHARINDEX(',', [Types]) <> 0 then substring([Types], 1, CHARINDEX(',', [Types])-1) else [Types] end as [Type]
from Types
union all
select [ID], [SN], [Index] + 1 as [Index],
case when CHARINDEX(',', [Types]) <> 0 then substring([Types], CHARINDEX(',', [Types])+1, 1000) else '' end as [Types],
case when CHARINDEX(',', [Types]) <> 0 then substring([Types], 1, CHARINDEX(',', [Types])-1) else [Types] end as [Type]
from TypesSplit
where LEN([Types])>0
)
select [ID],[SN],
max(case when [Index]=1 then [Type] end) as Types1,
max(case when [Index]=2 then [Type] end) as Types2,
max(case when [Index]=3 then [Type] end) as Types3,
max(case when [Index]=4 then [Type] end) as Types4,
max(case when [Index]=5 then [Type] end) as Types5,
max(case when [Index]=6 then [Type] end) as Types6,
max(case when [Index]=7 then [Type] end) as Types7,
max(case when [Index]=8 then [Type] end) as Types8
from TypesSplit
group by [ID],[SN]
(演示:http://www.sqlfiddle.com/#!6/c522f/9)
基本思路是使用CHARINDEX查找每个逗号的位置,然后SUBSTRING从头开始分割每种类型。递归循环遍历所有类型,直到没有剩余的消费。类型通过[Index]
列编号,以允许在输出中以相同的顺序再现它们。输出基本上是递归CTE生成的行数据的数据透视表,在旋转之前看起来像这样:
| ID | SN | INDEX | TYPES | TYPE |
|----|-----|-------|------------------------------|------|
| 1 | 123 | 1 | XYZ,TEST,RJK,CDF,TTT,UMB,UVX | ABC |
| 2 | 234 | 1 | CDF,TTT,UMB,UVX,TTT,UMB,UVX | RJK |
| 3 | 345 | 1 | XYZ,TTT,UMB,UVX,TTT,UMB,UVX | OID |
| 3 | 345 | 2 | TTT,UMB,UVX,TTT,UMB,UVX | XYZ |
| 3 | 345 | 3 | UMB,UVX,TTT,UMB,UVX | TTT |
| 3 | 345 | 4 | UVX,TTT,UMB,UVX | UMB |
| 3 | 345 | 5 | TTT,UMB,UVX | UVX |
| 3 | 345 | 6 | UMB,UVX | TTT |
| 3 | 345 | 7 | UVX | UMB |
| 3 | 345 | 8 | | UVX |
| 2 | 234 | 2 | TTT,UMB,UVX,TTT,UMB,UVX | CDF |
| 2 | 234 | 3 | UMB,UVX,TTT,UMB,UVX | TTT |
| 2 | 234 | 4 | UVX,TTT,UMB,UVX | UMB |
| 2 | 234 | 5 | TTT,UMB,UVX | UVX |
| 2 | 234 | 6 | UMB,UVX | TTT |
| 2 | 234 | 7 | UVX | UMB |
| 2 | 234 | 8 | | UVX |
| 1 | 123 | 2 | TEST,RJK,CDF,TTT,UMB,UVX | XYZ |
| 1 | 123 | 3 | RJK,CDF,TTT,UMB,UVX | TEST |
| 1 | 123 | 4 | CDF,TTT,UMB,UVX | RJK |
| 1 | 123 | 5 | TTT,UMB,UVX | CDF |
| 1 | 123 | 6 | UMB,UVX | TTT |
| 1 | 123 | 7 | UVX | UMB |
| 1 | 123 | 8 | | UVX |
旋转后,最终输出如下:
| ID | SN | TYPES1 | TYPES2 | TYPES3 | TYPES4 | TYPES5 | TYPES6 | TYPES7 | TYPES8 |
|----|-----|--------|--------|--------|--------|--------|--------|--------|--------|
| 1 | 123 | ABC | XYZ | TEST | RJK | CDF | TTT | UMB | UVX |
| 2 | 234 | RJK | CDF | TTT | UMB | UVX | TTT | UMB | UVX |
| 3 | 345 | OID | XYZ | TTT | UMB | UVX | TTT | UMB | UVX |