问题描述
我想用以下4个列在sql中创建一个表:id,年,月和日。但是,我想从2012年到2020年自动填写此栏。最佳方法是什么?我用谷歌搜索,但我真的找不到解决方案。例如,我希望表格显示以下信息。
overflow: hidden
解决方法
使用 VBoka 建议,请尝试以下操作:
create table calendar(
id int identity(1,1) not null primary key,ano int not null,mes int not null,dia int not null
)
declare @startdate date,@enddate date,@num_days int
set @startdate = '2012-01-01'
set @num_days = 3287 --number of days bewtween jan 2012 and dez 2020 https://www.timeanddate.com/date/durationresult.html
set @enddate = dateadd(d,@num_days,@startdate)
while @startdate <= @enddate
begin
insert into calendar (ano,mes,dia)
select year(@startdate),month(@startdate),day(@startdate)
set @startdate = dateadd(dd,1,@startdate)
end
,
使用CTE且没有日期时间功能:
if object_id('Calendar_tb','U') is null
create table Calendar_tb (
id int identity(1,1) not null,[year] smallint,[month] tinyint,[day] tinyint
)
declare @tb table (yy smallint,mm tinyint,dd tinyint);
with
CTE_y as (
select 2012 as nyear
union all
select nyear + 1 from CTE_y where nyear < 2020
),CTE_m as (
select 1 as nmonth
union all
select nmonth + 1 from CTE_m where nmonth < 12
),CTE_d as (
select 1 as nday
union all
select nday + 1 from cte_d where nday < 31
)
insert @tb
select nyear,nmonth,nday from CTE_d,CTE_m,CTE_y
delete from @tb
where (dd>30 and mm in (4,6,9,11))
or (dd>29 and mm = 2)
or (dd>28 and mm = 2 and not
-- leap year
(yy%400=0 or (yy%4=0 and yy%100!=0)))
truncate table Calendar_tb
insert Calendar_tb
select * from @tb order by 1,2,3
select * from Calendar_tb
,
不需要循环,游标或递归CTE ...就像下面这样简单。
WITH
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1)) n (n)),-- 10
cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b),-- 100
cte_Calendar (dt) AS (
SELECT TOP (DATEDIFF(DAY,'2012-01-01','2020-12-31') + 1)
CONVERT(DATE,DATEADD(DAY,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1,'2012-01-01'))
FROM
cte_n2 a CROSS JOIN cte_n2 b -- 10,000
)
SELECT
ID = DATEDIFF(DAY,c.dt) + 1,[Year] = YEAR(c.dt),[Month] = MONTH(c.dt),[Day] = DAY(c.dt)
FROM
cte_Calendar c;
GO
或者您可以用它来填充一个永久表...
IF OBJECT_ID('tempdb.dbo.YMD','U') IS NOT NULL
BEGIN DROP TABLE tempdb.dbo.YMD; END;
GO
CREATE TABLE tempdb.dbo.YMD (
ID int NOT NULL IDENTITY(1,1)
CONSTRAINT pk_YMD PRIMARY KEY CLUSTERED (ID),[Year] int NOT NULL,[Month] tinyint NOT NULL,[Day] tinyint NOT NULL
);
GO
--------------------------------------------------------------------------------------------------------
WITH
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),000
)
INSERT tempdb.dbo.YMD (Year,Month,Day)
SELECT
[Year] = YEAR(c.dt),[Day] = DAY(c.dt)
FROM
cte_Calendar c;
GO
------------------------------------------------------------------------------------------------------
SELECT
YMD.ID,YMD.Year,YMD.Month,YMD.Day
FROM
tempdb.dbo.YMD;
GO