sqlserver中的数据列就像 的数 1000-1050,1054,1090-1230,1245
numbers
-------
1000-1050, 1054, 1090-1230, 1245
如何获得如下风格:
numbers
-------
1000
1001
1002
1003
1004
...
1050
1054
1090
1091
1092
...
1245
答案 0 :(得分:0)
您可以使用拆分功能和APPLY
这样的
DECLARE @SampleData AS TABLE
(
numbers varchar(200)
)
INSERT INTO @SampleData
VALUES ('1000-1050, 1054, 1090-1230, 1245')
;WITH temp AS
(
SELECT 1 AS Number
UNION ALL
SELECT t.Number + 1 FROM temp t
WHERE t.Number < 5000
) -- return table from 1 --> 5000
SELECT DISTINCT
ca2.*
FROM @SampleData sd
CROSS APPLY
(
SELECT pos, LTRIM(Value) AS Value
FROM dbo.SplitString(sd.Numbers,',')
) ca1
CROSS APPLY
(
SELECT *
FROM temp t WHERE t.Number BETWEEN LEFT(ca1.[Value], charindex('-', ca1.[Value] + '-') - 1) AND
CASE
WHEN len(ca1.[Value]) < charindex('-', ca1.[Value] + '-') THEN ca1.[Value]
ELSE RIGHT(ca1.[Value], len(ca1.[Value]) - charindex('-', ca1.[Value] + '-'))
END
) ca2
OPTION (MAXRECURSION 0)
分割功能
CREATE FUNCTION [dbo].[SplitString] (@Text varchar(max),@Delimiter varchar(10))
Returns Table
As
Return (
Select Pos = Row_Number() over (Order By (Select null))
,Value = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(@Text,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
答案 1 :(得分:0)
首先拆分逗号分隔值,然后使用递归公用表表达式获取值。
Declare @values nvarchar(max) = '1000-1050, 1054, 1090-1230, 1245'
;with ranges_cte as
(
select cast(case pos when 0 then ResultValue else left(ResultValue,pos-1) end as int) first, cast(case pos when 0 then ResultValue else substring(ResultValue,pos+1,len(ResultValue)-pos) end as int) Last
from (
select ResultValue, charINDEx('-',ResultValue) pos
from dbo.SplitString(@values,',')) x
)
, values_rte as
(
select first,last,first as active
from ranges_cte
union all
select first,last,active +1 as active
from values_rte
where active< last
)
select *
from values_rte
OPTION (MAXRECURSION 0)
分割值的功能:
Create FUNCTION [dbo].[SplitString] (@StringArray NVARCHAR(MAX), @Delimiter NVARCHAR(10))
RETURNS @ResultedValues table
(
nr int,
ResultValue nvarchar(max)
)
AS
--select * from dbo.splitstring ('123,456,789',',')
BEGIN
declare @string nvarchar(max)
declare @nr int = 1
set @string = @StringArray
WHILE (CHARINDEX(@Delimiter,@String)>0)
BEGIN
INSERT INTO @ResultedValues (nr,ResultValue) VALUES (@nr,LTRIM(RTRIM(SUBSTRING(@String,1,CHARINDEX(@Delimiter,@String)-1))))
SET @String = SUBSTRING(@String, CHARINDEX(@Delimiter,@String)+LEN(@Delimiter),LEN(@String))
set @nr = @nr +1
END
INSERT INTO @ResultedValues (nr,ResultValue ) VALUES ( @nr, LTRIM(RTRIM(@String)))
RETURN
END
答案 2 :(得分:0)
创建拆分功能:
CREATE FUNCTION [dbo].[SplitIDsTest]
(
@idList varchar(4000)
)
RETURNS @parsedList TABLE
(
Id varchar(50),
Nr int
)
AS
BEGIN
DECLARE @id varchar(10), @pos int
DECLARE @nr int = 0;
SET @idList = LTRIM(RTRIM(@idList)) + ','
SET @Pos = CHARINDEX(',', @idList)
IF REPLACE(@idList, ',', '') <> ''
BEGIN
WHILE @Pos > 0
BEGIN
SET @id = LTRIM(RTRIM(LEFT(@idList, @pos - 1)))
IF @id <> ''
BEGIN
set @nr += 1;
INSERT INTO @ParsedList (Id, Nr)
VALUES (@id, @nr);
END
SET @idList = RIGHT(@idList, LEN(@idList) - @pos) -- 'WMPC,' (inklusive Komma) links vom Eingabeparameter abschneiden, weil jetzt der nächste Wert gesucht wird
SET @pos = CHARINDEX(',', @idList, 1) -- Nächste Position eines Kommas suchen und in der WHILE-Schleife weitermachen
END
END
RETURN
END
然后是一个计数表:
select top 1000000 N=identity(int, 1, 1)
into dbo.Tally
from master.dbo.syscolumns a cross join master.dbo.syscolumns b;
然后使用:
select distinct Tally.N
from SplitIDsTest('10-12, 34, 9') splitted
join Tally on 1 = case
when CHARINDEX('-', splitted.Id) > 0 then
case
when Tally.N between cast(left(splitted.Id, CHARINDEX('-', splitted.Id) - 1) as int)
and cast(right(splitted.Id, len(splitted.Id) - CHARINDEX('-', splitted.Id)) as int) then 1
else 0
end
when Tally.N = cast(splitted.Id as int) then 1
else 0
end
order by Tally.N