SQL Server如何检索2个数字之间的所有数字
我有4列-代码、金额、开始、结束。我想在开始列和结束列之间取金额,并将其更改为包含所有结果的一列。对如何实现这一目标有何建议?谢谢SQL Server如何检索2个数字之间的所有数字,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有4列-代码、金额、开始、结束。我想在开始列和结束列之间取金额,并将其更改为包含所有结果的一列。对如何实现这一目标有何建议?谢谢 Current Results: Code Amount Start End 1 5000 2015 2016 2 5000 2014 2016 3 20000 2012 2016 Desired Results: Code Amount StartEnd 1 5000 2015 1
Current Results:
Code Amount Start End
1 5000 2015 2016
2 5000 2014 2016
3 20000 2012 2016
Desired Results:
Code Amount StartEnd
1 5000 2015
1 5000 2016
2 5000 2014
2 5000 2015
2 5000 2016
3 20000 2012
3 20000 2013
3 20000 2014
3 20000 2015
3 20000 2016
您可以使用递归cte生成最小开始和最大结束之间的所有数字,并在生成的数字上进行连接
with cte as (select min(start) col,max(end) mx from tablename
union all
select col+1,mx from cte where col < mx)
select t.code,t.amount,c.col
from cte c
join tablename t on c.col between t.start and t.end
或者更简单地说
with cte as (select id,amount,start startend,end from tablename
union all
select id,amount,start+1,end from cte where start<end)
select id,amount,startend
from cte
order by 1,3
另一个选择是UDF。我使用这个TVF来生成动态范围
Declare @YourTable table (Code int, Amount int, Start int , [End] int)
Insert into @YourTable values
(1,5000 ,2015,2016),
(2,5000 ,2014,2016),
(3,20000,2012,2016)
Select A.Code
,A.Amount
,StartEnd = cast(B.RetVal as int)
From @YourTable A
Cross Apply (Select * from [dbo].[udf-Range-Number](A.Start,A.[End],1)) B
返回
Code Amount StartEnd
1 5000 2015
1 5000 2016
2 5000 2014
2 5000 2015
2 5000 2016
3 20000 2012
3 20000 2013
3 20000 2014
3 20000 2015
3 20000 2016
功能
CREATE FUNCTION [dbo].[udf-Range-Number] (@R1 money,@R2 money,@Incr money)
Returns Table
Return (
with cte0(M) As (Select cast((@R2-@R1)/@Incr as int)),
cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (Select M from cte0) Row_Number() over (Order By (Select NULL)) From cte1 a,cte1 b,cte1 c,cte1 d,cte1 e,cte1 f,cte1 g,cte1 h )
Select RetSeq=1,RetVal=@R1 Union All Select N+1,(N*@Incr)+@R1
From cte2
)
/*
Max 100 million observations --
Syntax:
Select * from [dbo].[udf-Range-Number](0,4,0.25)
*/
我不确定它是否适用于SQL 2008,但这里有一个CTE:
;with sel_cte as (
select Code, Amount, start StartEnd
from @tblTest t
union all
select t.code, t.amount, c.StartEnd + 1 StartEnd
from sel_cte c
inner join @tblTest t on t.code = c.code
where c.StartEnd + 1 <= [end]
)
select *
from sel_cte
order by Code, StartEnd
注:将@tblTest替换为实际的表名。如果要求只允许您有连续的数字,如2014、2015、2016等,则上述cte方法可以正常工作。但是,如果没有,您可以创建另一个临时表,比如说数字,它有一列,数字按照您想要的结果输出的连续顺序排列,比如
Number
2014
2015
2016
2018 <-- Missing 2017 and jumping on 2018
2019
您可以这样查询
SELECT
c.code,
c.amount,
f.yr
FROM #code c
CROSS APPLY fn_yearslist(c.startyr, c.endyr) f
CREATE FUNCTION fn_yearslist (@startyear int, @endyear int)
RETURNS @t TABLE (
yr int
)
AS
BEGIN
WHILE (@startyear <= @endyear)
BEGIN
INSERT INTO @t (yr)
VALUES (@startyear)
SET @startyear += 1
END
RETURN
END
您可以这样创建函数
SELECT
c.code,
c.amount,
f.yr
FROM #code c
CROSS APPLY fn_yearslist(c.startyr, c.endyr) f
CREATE FUNCTION fn_yearslist (@startyear int, @endyear int)
RETURNS @t TABLE (
yr int
)
AS
BEGIN
WHILE (@startyear <= @endyear)
BEGIN
INSERT INTO @t (yr)
VALUES (@startyear)
SET @startyear += 1
END
RETURN
END
哪个版本的sql server?对不起,现在是2008年。也许我错了。。。左连接意味着如果有年份没有值,那么将有一行只有最后一列和null,所以我猜它一直到最后一列op@Hogan .. 这里不需要左连接。右连接,除非他想显示没有任何范围的年份。我没有看到两件事1这与OP明确说明的问题有什么关系检索2个数字之间的所有数字表示连续的数字。2您提到,如果需要,您可以填充另一个临时表,但您没有显示任何方法,也没有讨论它的逻辑。也许您认为cte方法将获取表的最大值和最小值,并生成所有数字。所以,如果有中断,比如说第3行,从2009年开始到2012年结束,那么您将丢失2013年的数据?但cte实际上也可以忽略2013年,另一个表格的方法可能会在未来引入跳过数字的额外灵活性。我忽略了创建和插入单列表的细节,因为我假设具有连续数字的单列表应该易于创建和填充。此外,使用cte方法忽略或跳过一个数字需要硬编码。抱歉,但我来自一个完整的堆栈背景有所有这些想法固有的。