我有一个包含如下列数据的数据库表:
Data (field name)
1111,44,666,77
22,55,76,54
32,31,56
我意识到这是一个非常糟糕的设计,因为它没有标准化(我没有设计它 - 我继承了它)。是否有一个查询会返回这样的数据:
1111
44
666
77
22
55
76
54
32
31
56
我习惯使用 CHARINDEX 和 SUBSTRING,但我想不出这样做的方法,因为每个单元格中的元素数量(由逗号分隔)是未知的。
我有一个包含如下列数据的数据库表:
Data (field name)
1111,44,666,77
22,55,76,54
32,31,56
我意识到这是一个非常糟糕的设计,因为它没有标准化(我没有设计它 - 我继承了它)。是否有一个查询会返回这样的数据:
1111
44
666
77
22
55
76
54
32
31
56
我习惯使用 CHARINDEX 和 SUBSTRING,但我想不出这样做的方法,因为每个单元格中的元素数量(由逗号分隔)是未知的。
我创建了一个名为 [dbo].[stack] 的表,并用您提供的数据填充它,这个脚本产生了您需要的数据。可能有一种更有效的方法可以做到这一点,但这完全符合您的要求。
BEGIN
DECLARE @tmp TABLE (data VARCHAR(20))
DECLARE @tmp2 TABLE (data VARCHAR(20))
--Insert all fields from your table
INSERT INTO @tmp (data)
SELECT [data]
FROM [dbo].[stack] -- your table name here
--Loop through all the records in temp table
WHILE EXISTS (SELECT 1
FROM @tmp)
BEGIN
DECLARE @data VARCHAR(100) --Variable to chop up
DECLARE @data1 VARCHAR(100) -- Untouched variable to delete from tmp table
SET @data = (SELECT TOP 1 [data]
FROM @tmp)
SET @data1 = (SELECT TOP 1 [data]
FROM @tmp)
--Loop through variable to get individual value
WHILE PATINDEX('%,%',@data) > 0
BEGIN
INSERT INTO @tmp2
SELECT SUBSTRING(@data,1,PATINDEX('%,%',@data)-1);
SET @data = SUBSTRING(@data,PATINDEX('%,%',@data)+1,LEN(@data))
IF PATINDEX('%,%',@data) = 0
INSERT INTO @tmp2
SELECT @data
END
DELETE FROM @tmp
WHERE [data] = @data1
END
SELECT * FROM @tmp2
END
您可以使用 CTE 拆分数据:
;with cte (DataItem, Data) as
(
select cast(left(Data, charindex(',',Data+',')-1) as varchar(50)) DataItem,
stuff(Data, 1, charindex(',',Data+','), '') Data
from yourtable
union all
select cast(left(Data, charindex(',',Data+',')-1) as varchar(50)) DataItem,
stuff(Data, 1, charindex(',',Data+','), '') Data
from cte
where Data > ''
)
select DataItem
from cte
结果:
| DATAITEM |
------------
| 1111 |
| 22 |
| 32 |
| 31 |
| 56 |
| 55 |
| 76 |
| 54 |
| 44 |
| 666 |
| 77 |
或者您可以创建一个拆分功能:
create FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))
returns @temptable TABLE (items varchar(MAX))
as
begin
declare @idx int
declare @slice varchar(8000)
select @idx = 1
if len(@String)<1 or @String is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
insert into @temptable(Items) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
return
end;
您可以在查询时使用它,这将产生相同的结果:
select s.items declaration
from yourtable t1
outer apply dbo.split(t1.data, ',') s
SELECT REPLACE(field_name, ',', ' ') from table
编辑:当你改变你的问题时,不要介意这个答案。
不谈论性能,您可以将数据连接到单个列中,然后将其拆分。
看看在类似问题中引用的这篇文章:
http://www.codeproject.com/Articles/7938/SQL-User-Defined-Function-to-Parse-a-Delimited-Str
如果您创建他们在那篇文章中拥有的函数,您可以使用以下方法调用它:
select * from dbo.fn_ParseText2Table('100|120|130.56|Yes|Cobalt Blue','|')