2016-09-29 53 views
2

我有4列 - 代碼,金額,開始,結束。我想要在開始和結束列中的數量之間進行比較,並將它們更改爲具有所有結果的一列。有關如何實現這一目標的任何建議?謝謝。SQL Server如何檢索2個數字之間的所有數字

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 
+0

哪個版本的SQL Server的本

SELECT c.code, c.amount, f.yr FROM #code c CROSS APPLY fn_yearslist(c.startyr, c.endyr) f 

功能? – techspider

+0

對不起,2008年。 – ajc101

回答

5

您可以使用遞歸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 

或更簡單地

​​
+0

也許我錯了...左加入意味着,如果有沒有價值的年份,將只有一行只有最後一列和空值,所以我想它的操作 – Hogan

+0

@霍根..離開這裏不需要加入。 –

+0

沒錯,除非他想顯示沒有任何範圍的年份。 – Hogan

1

另一種選擇是一個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((@[email protected])/@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,[email protected] Union All Select N+1,(N*@Incr)[email protected] 
    From cte2 
) 
/* 
Max 100 million observations -- 
Syntax: 
Select * from [dbo].[udf-Range-Number](0,4,0.25) 
*/ 
0

我不知道這是否適用於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替換爲實際的表名。

-1

如果要求允許您只有連續的數字(如2014年,2015年,然後2016年等),那麼上述方法(cte)將工作正常。但是,如果沒有,你可以創建另一個臨時表(比如說有1列的數字),並且按照你想要的結果輸出的連續順序編號。

Number 
2014 
2015 
2016 
2018 <-- Missing 2017 and jumping on 2018 
2019 

然後使用右連接以漸進系列的形式獲得結果,查詢類似於下面的查詢。

select Code, StartEnd, Amount from numbers 
    right join inputs on number between Start and End 
+0

我沒有看到一些事情1)這與OP已經明確指出「檢索2個數字之間的所有數字」表示連續數字的問題有什麼關係。 2)你提到你可以填充另一個臨時表,如果你想,但你沒有展示如何做到這一點或討論它的邏輯的任何方法。也許你認爲cte方法會取得表格的最大和最小值並生成所有數字。因此,如果有突破,讓我們說行3在哪裏開始2009年結束2012年,那麼你會錯過2013年的數據?但該cte實際上可以忽略2013年 – Matt

+0

另一個表的方法可能會引入跳過數字的額外的靈活性,可能是,未來。我錯過了創建和插入單孔表格的細節,假設單字表格連續編號應該易於創建和填充。而且,使用cte方法忽略或跳過數字將需要硬編碼。對不起,我是從全棧背景來的,所有這些想法都是固有的。 – ash

0

您可以查詢像你cancreate這樣

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 
相關問題