Moo*_*ght 6 sql t-sql common-table-expression sql-server-2012
我有以下表定义
CREATE TABLE _Table
(
[Pat] NVARCHAR(8),
[Codes] NVARCHAR(50),
[C1] NVARCHAR(6),
[C2] NVARCHAR(6),
[C3] NVARCHAR(6),
[C4] NVARCHAR(6),
[C5] NVARCHAR(6)
);
GO
INSERT INTO _Table ([Pat], [Codes], [C1], [C2], [C3], [C4], [C5])
VALUES
('Pat1', 'U212,Y973,Y982', null, null, null, null, null),
('Pat2', 'M653', null, null, null, null, null),
('Pat3', 'U212,Y973,Y983,Z924,Z926', null, null, null, null, null);
GO
Run Code Online (Sandbox Code Playgroud)
现在,我想分割每行的代码并填充Cn列,以便最终得到
Pat Codes C1 C2 C3 C4 C5
Pat1 'U212,Y973,Y982' U212 Y973 Y982 NULL NULL
Pat2 'M653' M653 NULL NULL NULL NULL
Pat3 'U212,Y973,Y983,Z924,Z926' U212 Y973 Y983 Z924 Z926
Run Code Online (Sandbox Code Playgroud)
我正在研究动态SQL,但有更好的方法......
我已经开始了CTE路线,但我在这里很弱.我基本上是循环,删除第一个逗号分隔的代码,并使用左来获取该代码并选择它C1.
;WITH tmp([Pat], [Codes], [C1], [C2], [C3], [C4], [C5]) AS
(
SELECT
Pat,
STUFF(Codes, 1, CHARINDEX(',', Codes + ','), ''),
LEFT(Codes, CHARINDEX(',', Codes + ',') - 1),
[C2],
[C3],
[C4],
[C5]
FROM _Table
UNION all
SELECT
Pat,
STUFF(Codes, 1, CHARINDEX(',', Codes + ','), ''),
LEFT(Codes, CHARINDEX(',', Codes + ',') - 1),
[C2],
[C3],
[C4],
[C5]
FROM _Table
WHERE
Codes > ''
)
SELECT Pat, Codes, [C1], [C2], [C3], [C4], [C5]
FROM tmp
ORDER BY Pat
Run Code Online (Sandbox Code Playgroud)
这适用于一个代码,但我如何做所有5?注意,在实践中,这可以增加到N个代码.
如果我正确理解要求,这非常简单.不需要拆分或其他类型的功能,动态SQL,递归CTE,PIVOTING或任何其他技术.
要执行"拆分",您可以这样使用CROSS APPLY:
SELECT
Pat,
Codes,
C1 = SUBSTRING(Codes,1,ISNULL(d1.d-1,8000)),
C2 = SUBSTRING(Codes,d1.d+1, d2.d-d1.d-1),
C3 = SUBSTRING(Codes,d2.d+1, d3.d-d2.d-1),
C4 = SUBSTRING(Codes,d3.d+1, d4.d-d3.d-1),
C5 = SUBSTRING(Codes,d4.d+1, 8000)
FROM _Table
CROSS APPLY (VALUES (NULLIF(CHARINDEX(',',Codes),0))) d1(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(',',Codes,d1.d+1),0))) d2(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(',',Codes,d2.d+1),0))) d3(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(',',Codes,d3.d+1),0))) d4(d);
Run Code Online (Sandbox Code Playgroud)
返回
Pat Codes C1 C2 C3 C4 C5
-------- ----------------------------- ----- ------ ----- ----- ------
Pat1 U212,Y973,Y982 U212 Y973 NULL NULL NULL
Pat2 M653 M653 NULL NULL NULL NULL
Pat3 U212,Y973,Y983,Z924,Z926 U212 Y973 Y983 Z924 Z926
Run Code Online (Sandbox Code Playgroud)
请注意超级简单且超高效的执行计划:
如果代码总是四个字符,你可以进一步简化这个:
SELECT
Pat,
Codes,
C1 = NULLIF(SUBSTRING(Codes,1,4),''),
C2 = NULLIF(SUBSTRING(Codes,6,4),''),
C3 = NULLIF(SUBSTRING(Codes,11,4),''),
C4 = NULLIF(SUBSTRING(Codes,16,4),''),
C2 = NULLIF(SUBSTRING(Codes,21,4),'')
FROM _Table;
Run Code Online (Sandbox Code Playgroud)
要执行更新,您将为第一个解决方案执行此操作:
UPDATE _Table
SET
C1 = SUBSTRING(Codes,1,ISNULL(d1.d-1,8000)),
C2 = SUBSTRING(Codes,d1.d+1, d2.d-d1.d-1),
C3 = SUBSTRING(Codes,d2.d+1, d3.d-d2.d-1),
C4 = SUBSTRING(Codes,d3.d+1, d4.d-d3.d-1),
C5 = SUBSTRING(Codes,d4.d+1, 8000)
FROM _Table
CROSS APPLY (VALUES (NULLIF(CHARINDEX(',',Codes),0))) d1(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(',',Codes,d1.d+1),0))) d2(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(',',Codes,d2.d+1),0))) d3(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(',',Codes,d3.d+1),0))) d4(d);
Run Code Online (Sandbox Code Playgroud)
如果代码再次只有四个字符,则更新非常简单,感觉就像作弊:
UPDATE _Table
SET C1 = NULLIF(SUBSTRING(Codes,1,4),''),
C2 = NULLIF(SUBSTRING(Codes,6,4),''),
C3 = NULLIF(SUBSTRING(Codes,11,4),''),
C4 = NULLIF(SUBSTRING(Codes,16,4),''),
C5 = NULLIF(SUBSTRING(Codes,21,4),'');
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
179 次 |
| 最近记录: |