Table Normalization (Parse comma separated fields into individual records)
我有一张这样的桌子:
设备
1
2 3 4 5 |
DeviceId Parts
1 Part1, Part2, Part3 |
我想创建一个表 \\’Parts\\’,将 Parts 列中的数据导出到新表。之后我将删除 Parts 列
预期结果
零件
1
2 3 4 5 6 |
PartId PartName
1 Part1 |
设备部件
1
2 3 4 5 6 7 8 9 |
DeviceId PartId
1 1 |
我可以在 SQL Server 2008 中不使用游标来执行此操作吗?
- 你试过什么了。这里需要的一个提示是一个带有 partID(Int, Identity(1,1)),partname 的表,并使用 select distinct 插入到该表中。之后,一个 Join 将为您提供第二个表..
- 到目前为止,我已经尝试过游标,但我不喜欢这个解决方案,我觉得应该有更好的方法来做到这一点。
— 设置:
1
2 3 4 5 6 7 8 9 |
DECLARE @Device TABLE(DeviceId INT PRIMARY KEY, Parts VARCHAR(1000))
DECLARE @Part TABLE(PartId INT IDENTITY(1,1) PRIMARY KEY, PartName VARCHAR(100)) DECLARE @DevicePart TABLE(DeviceId INT, PartId INT) INSERT @Device |
–脚本:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
DECLARE @DevicePartTemp TABLE(DeviceId INT, PartName VARCHAR(100))
INSERT @DevicePartTemp
INSERT @Part INSERT @DevicePart |
— 结果:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
SELECT *
FROM @Part PartId PartName
SELECT * DeviceId PartId |
您将需要一个 Tally 表来完成此操作,而无需使用光标。
按照说明在此处创建计数表:Jeff Moden 的计数表
此脚本会将表放入您的 Temp 数据库,因此您可能想要更改 “Use DB” 语句
然后您可以运行下面的脚本将设备和部件的细分插入到临时表中。然后,您应该能够通过部件名称加入您的部件表(以获取 ID)并插入到新的 DevicePart 表中。
1
2 3 4 5 6 7 8 |
SELECT *,
–substring(d.parts, 1, t.n) SUBSTRING(d.parts, t.n, charindex(‘, ‘, d.parts + ‘, ‘,t.n) – t.n) ‘Part’ INTO #devicesparts FROM device d CROSS JOIN tally t WHERE t.n < (SELECT MAX(len(parts))+ 1 FROM device) AND SUBSTRING(‘, ‘ + d.parts, t.n, 1) = ‘, ‘ |
如果每个设备有最大零件数,是的,可以在没有光标的情况下完成,但这很复杂。
基本上,为 PartID 字符串中的每个可能索引创建一个表(或视图或子查询),其中包含一个 DeviceID 和一个 PartID 列。这可以通过使用 fn_split 或您选择的其他方法使 PartID 列计算列来完成。从那里您对该表执行多个自联合,每个 PartID 列的自联合中都有一个表。 self-UNION 中的每个表只有一个 PartID 列包含在该表的查询的选择列表中。
看看使用 fn_Split 从逗号分隔值创建表变量。
然后,您可以使用它来驱动插入。
编辑:实际上,我认为您可能仍然需要一个光标。留下这个答案以防 fn_Split 有帮助。
- 老天,请不要使用那个功能。它使用 mTVF 和 WHILE 循环。它是可用的最慢的分离器之一。
来源:https://www.codenong.com/6418214/