SQL如何将一列拆分为多个变量列
我正在使用MSSQL,试图将一个字符串列拆分为多个列。字符串列包含以分号分隔的数字,如:SQL如何将一列拆分为多个变量列,sql,sql-server-2008,tsql,Sql,Sql Server 2008,Tsql,我正在使用MSSQL,试图将一个字符串列拆分为多个列。字符串列包含以分号分隔的数字,如: 190230943204;190234443204; 但是,有些行的数字比其他行多,因此在数据库中可以 190230943204;190234443204; 121340944534;340212343204;134530943204 我见过一些将一列拆分为特定数量列的解决方案,但不是可变列。数据较少的列(由逗号分隔的2系列字符串而不是3个字符串)的第三位将为空 想法?如果我必须澄清任何事情,请告诉我。
190230943204;190234443204;
但是,有些行的数字比其他行多,因此在数据库中可以
190230943204;190234443204;
121340944534;340212343204;134530943204
我见过一些将一列拆分为特定数量列的解决方案,但不是可变列。数据较少的列(由逗号分隔的2系列字符串而不是3个字符串)的第三位将为空
想法?如果我必须澄清任何事情,请告诉我。将此数据拆分为单独的列是一个非常好的开始(分离的值是一种异端邪说)。但是,“可变数量的属性”通常应建模为一个属性
entity\u properties.main\u entity\u id
是一个tomain\u entity.id
祝贺你,你在正确的道路上,这就是所谓的。你即将到达终点
然而,Beweare的这些属性应该具有相似的性质(即所有电话号码或地址等)。不要落入黑暗面(又称“黑暗面”),不要试图将所有财产都放在同一张桌子上。如果您可以识别几种类型的属性,请将每种类型存储在一个单独的表中。如果这些都是固定长度的字符串(如问题中所述),那么您可以相当简单地完成这项工作(至少相对于其他解决方案):
选择子字符串(col,1+13*(n-1),12)作为val
从t连接
(选择1作为n联合所有选择联合所有选择3
)n
如果我是你,我会在len(t.col)上创建一个简单的函数,用“;”分隔值像这样:
IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'fn_Split_List') AND xtype IN (N'FN', N'IF', N'TF'))
BEGIN
DROP FUNCTION [dbo].[fn_Split_List]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fn_Split_List](@List NVARCHAR(512))
RETURNS @ResultRowset TABLE ( [Value] NVARCHAR(128) PRIMARY KEY)
AS
BEGIN
DECLARE @XML xml = N'<r><![CDATA[' + REPLACE(@List, ';', ']]></r><r><![CDATA[') + ']]></r>'
INSERT INTO @ResultRowset ([Value])
SELECT DISTINCT RTRIM(LTRIM(Tbl.Col.value('.', 'NVARCHAR(128)')))
FROM @xml.nodes('//r') Tbl(Col)
RETURN
END
GO
SELECT SL.[Value]
FROM @RawData AS RD
CROSS APPLY [fn_Split_List] ([Value]) as SL
WHERE LEN(SL.[Value]) > 0
结果如下:
Value
1111111
22222222
113113131
3333333
776767676
313131312
54545353
89332131
无论如何,函数中的逻辑并不复杂,因此您可以轻松地将其放在需要的任何位置
注意:对于用“;”分隔的值的数量没有限制,但是,如果需要,可以将函数的长度限制设置为NVARCHAR(MAX)
编辑:
正如我所看到的,您的示例中有一些行将导致函数返回空字符串。例如:
number;number;
将返回:
number
number
'' (empty string)
要清除它们,只需在上面的语句中添加以下where子句,如下所示:
IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'fn_Split_List') AND xtype IN (N'FN', N'IF', N'TF'))
BEGIN
DROP FUNCTION [dbo].[fn_Split_List]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fn_Split_List](@List NVARCHAR(512))
RETURNS @ResultRowset TABLE ( [Value] NVARCHAR(128) PRIMARY KEY)
AS
BEGIN
DECLARE @XML xml = N'<r><![CDATA[' + REPLACE(@List, ';', ']]></r><r><![CDATA[') + ']]></r>'
INSERT INTO @ResultRowset ([Value])
SELECT DISTINCT RTRIM(LTRIM(Tbl.Col.value('.', 'NVARCHAR(128)')))
FROM @xml.nodes('//r') Tbl(Col)
RETURN
END
GO
SELECT SL.[Value]
FROM @RawData AS RD
CROSS APPLY [fn_Split_List] ([Value]) as SL
WHERE LEN(SL.[Value]) > 0
这是糟糕的数据设计。切勿在列中存储逗号分隔的数据。希望这里的目的是修复模式。你可以在这里找到你需要的:很抱歉,它们不是逗号,而是分号,用于分隔数据。可能的重复我看到了这个问题,它不是重复的,因为那里的人知道他将拆分成多少列(4)而我没有。它们确实是固定长度的字符串。你能澄清什么是“n”和“t.col”吗?什么是“val”?@user2522217t
是表的名称col
是包含字符串的列的名称n
和n.n
是子查询及其列的名称。
SELECT SL.[Value]
FROM @RawData AS RD
CROSS APPLY [fn_Split_List] ([Value]) as SL
WHERE LEN(SL.[Value]) > 0