生成序列SQL服务器的缺失年份

时间:2017-11-29 21:45:58

标签: sql-server

我有一个我需要分析的表格,多年来数据缺失,我想反映一下。前两列是位置代码,后两列是输入的最近年份。我能够获得每个位置的最小值和最大值,但是我想创建一个这样的序列来加入另一个表。每个位置都有不同的年份范围,所以基本上我必须为每个位置创建一个单独的范围。

给出结果

(Location Cds)  Start   End
0160,   002,    1995,   2009
0160,   001,    1995,   1997

目标结果

(Location Cds)  Years
0160,   001,    1995
0160,   001,    1996
0160,   001,    1997
0160,   002,    1995
0160,   002,    1996
0160,   002,    1997
0160,   002,    1998
0160,   002,    1999
0160,   002,    2000
0160,   002,    2001
0160,   002,    2002
0160,   002,    2003
0160,   002,    2004
0160,   002,    2005
0160,   002,    2006
0160,   002,    2007
0160,   002,    2008
0160,   002 ,   2009

1 个答案:

答案 0 :(得分:1)

计数表是这一挑战的答案。它被称为"瑞士军刀t-sql"并且有充分的理由。它可以做各种人们通常认为循环的事情。这是一篇很好的文章,讨论杰夫莫登的理货表。 http://www.sqlservercentral.com/articles/T-SQL/62867/

我喜欢在我的系统上保持一个视图,几乎立即生成10,000行,零读取。这是该观点。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally
GO

然后,当您遇到具有挑战性的查询时,就像您正在使用它一样,它非常简单。这是一个完整的工作示例,包括您发布的问题的ddl。在您的情况下,您将直接针对您的表运行此类查询。我使用了一个表变量,因为我没有你的表可以使用。

declare @Something table 
(
    Location varchar(10)
    , Cds varchar(10)
    , YearStart int
    , YearEnd int
)

insert @Something
(
    Location
    , Cds
    , YearStart
    , YearEnd
) values
('0160', '002', 1995, 2009)
, ('0160', '001', 1995, 1997)

select s.Location
    , s.Cds
    , Years = x.N 
from @Something s
cross apply
(
    select *
    from cteTally t
    where t.N >= s.YearStart
        and t.N <= s.YearEnd
) x
order by s.Location 
    , s.Cds
    , x.N