Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何通过SQL将逗号分隔的列与非唯一ID列一起拆分为行_Sql_Tsql_Split_Sql Server 2012 - Fatal编程技术网

如何通过SQL将逗号分隔的列与非唯一ID列一起拆分为行

如何通过SQL将逗号分隔的列与非唯一ID列一起拆分为行,sql,tsql,split,sql-server-2012,Sql,Tsql,Split,Sql Server 2012,我很想得到一些关于如何完成这项任务的建议。如何创建sql语句将表转换为所示的预期输出?如果你能指出正确的方向,我将不胜感激 是否可以仅在具有读取权限的情况下执行此操作?因此无法创建函数或额外的表。我有SQL server 2012,但可以升级到2016 编辑:对于前面ID列的错误示例,我真的很抱歉。ID列现在是唯一的主键。谢谢你的建议和帮助 Table: ID Value 100 aaa, bbb, ccc 101 aaa, bbb, ccc 102 aaa,

我很想得到一些关于如何完成这项任务的建议。如何创建sql语句将表转换为所示的预期输出?如果你能指出正确的方向,我将不胜感激

是否可以仅在具有读取权限的情况下执行此操作?因此无法创建函数或额外的表。我有SQL server 2012,但可以升级到2016

编辑:对于前面ID列的错误示例,我真的很抱歉。ID列现在是唯一的主键。谢谢你的建议和帮助

Table:
ID      Value
100     aaa, bbb, ccc
101     aaa, bbb, ccc
102     aaa, bbb, ccc
103     abc, bcb, zzz
104     abc, bcb, zzz
105     abc, bcb, zzz


Expected:
ID      Value
100     aaa
101     bbb
102     ccc
103     abc
104     bcb
105     zzz

对于这一个,你将需要杰夫·摩登的8K分裂函数,你可以找到它。一旦安装了该函数(在SQL Server 2016出现拆分字符串之前,您将多次使用该函数),您可以使用以下代码来解决问题:

DECLARE @t TABLE
(
Id INTEGER,
Val VARCHAR(20)
);

INSERT INTO @t VALUES
(1,'aaa,bbb,ccc'),
(1,'aaa,bbb,ccc'),
(1,'aaa,bbb,ccc'),
(2,'abc,bcb,zzz'),
(2,'abc,bcb,zzz'),
(2,'abc,bcb,zzz');

SELECT DISTINCT t.Id, item, ItemNumber
FROM @t t
CROSS APPLY [dbo].[DelimitedSplit8K](t.Val, ',');

--results
Id          item     RowNumber
----------- -------- --------------------
1           aaa      1
1           bbb      2
1           ccc      3
2           abc      1
2           bcb      2
2           zzz      3

为了改进上面Jim的回答,我建议我们在执行拆分之前使用删除重复项,如果可能的话。这将导致要筛选的重复项数量大大减少。使用此示例数据

CREATE TABLE #t
(
  Id  INT,
  Val VARCHAR(20)
);

INSERT INTO #t VALUES
(1,'aaa,bbb,ccc'),
(1,'aaa,bbb,ccc'),
(1,'aaa,bbb,ccc'),
(2,'abc,bcb,zzz'),
(2,'abc,bcb,zzz'),
(2,'abc,bcb,zzz');
。。。我们可以比较一下执行计划,看看我的意思。在启用“包括实际执行计划”的情况下运行:

-- Remove Duplicates BEFORE the split
SELECT t.Id, s.ItemNumber, s.item
FROM (SELECT DISTINCT t.* FROM #t AS t) AS t
CROSS APPLY [dbo].[DelimitedSplit8K](t.Val, ',') AS s;

-- Remove Duplicates AFTER the split
SELECT DISTINCT t.Id, s.ItemNumber, s.item
FROM #t AS t
CROSS APPLY [dbo].[DelimitedSplit8K](t.Val, ',') AS s; 
下面是执行计划。对于此示例数据,在拆分之前删除重复项会导致内部循环联接和合并联接运算符中出现6行,并且只有2行得到排序。拆分后删除重复项将导致循环和合并联接运算符中的18行以及6行得到排序


您确定您的表格数据正确吗?似乎每个
id
值只有一行,然后您希望将
value
列解析为单独的行。解析为三列是可行的。只需通过嵌套调用
charindex()
搜索逗号即可。使用
交叉应用
来获取多行。内置的
字符串-_分割
可能是在2016年引入的,而不是2017年版本。此外,在2016版本之前,还有其他拆分字符串的方法。阅读Aaron Bertrand的详细信息。还有一件事-您使用的
row_number()
与错误的
order by
-您应该在
order by
子句中使用
ItemNumber
(从Moden函数返回的第二列),否则,您将得到一个任意的行号,该行号可能是正确的,也可能是不正确的。我已经编辑了我的答案,以显示正确版本的拆分字符串。在id前端,它根据输入生成正确的结果。ID与我编写的查询相同。这里使用ItemNumber实际上没有什么区别,您的注释只会让事情变得更加混乱。
按Id按Id排序
意味着您是按常量值排序的,这与没有orderby一样任意。您可能会在测试中得到当前的结果,但没有任何东西可以保证它是一致的-这意味着,无论何时运行查询,您都有可能出现错误的顺序。很抱歉,英语不是我的母语,我不熟悉短语“遇到一个错误”。无论如何,很高兴我们能同意。