2010-11-15 157 views
6

我需要一个select来返回Month和Year在指定的日期范围内,我将输入开始年份和月份,并且select将从日期I返回月份和年份输入到今天。t-sql select获取一年内的所有月份

我知道我可以在循环中做到这一点,但我想知道是否有可能在一系列选择中做到这一点?

Year Month 
---- ----- 
2010 1 
2010 2 
2010 3 
2010 4 
2010 5 
2010 6 
2010 7 

等等。

+0

SQL Server 2008中 – 2010-11-15 04:04:49

回答

0
declare @date1 datetime, 
    @date2 datetime, 
    @date datetime, 
    @month integer, 
    @nm_bulan varchar(20) 

create table #month_tmp 
    (bulan integer null, keterangan varchar(20) null) 

select @date1 = '2000-01-01', 
     @date2 = '2000-12-31' 

select @month = month(@date1) 

while (@month < 13) 
Begin 
    IF @month = 1 
    Begin 
     SELECT @date = CAST(CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,0,@date1))-1),DATEADD(mm,0,@date1)),111) + ' 00:00:00' as DATETIME) 
    End 
    ELSE 
    Begin 
     SELECT @date = CAST(CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,@month -1,@date1))-1),DATEADD(mm,@month -1,@date1)),111) + ' 00:00:00' as DATETIME) 
    End 
    select @nm_bulan = DATENAME(MM, @date) 

    insert into #month_tmp 
    select @month as nilai, @nm_bulan as nama 

    select @month = @month + 1 
End 

select * from #month_tmp 
drop table #month_tmp 
go 
0

,你可以做以下

SELECT DISTINCT YEAR(myDate) as [Year], MONTH(myDate) as [Month] 
FROM myTable 
WHERE <<appropriate criteria>> 
ORDER BY [Year], [Month] 
+0

你会如何使用 “适当的标准” 就可以显示例子...就像从2009-12到今天的所有日期 – 2010-11-15 04:13:13

3

您可以使用这样的:http://blogs.msdn.com/b/sqlazure/archive/2010/09/16/10063301.aspx

以使用日期范围的数字表的等价物。

但是,您能否澄清您的输入和输出?

是否要输入开始日期,例如'2010-5-1'和结束日期,例如'2010-8-1',并且每两个月之间都会有一个回报?你想包括开始月份和结束月份,还是排除它们?

下面是我编写的一些代码,可以快速生成两个日期之间每个月的包含结果。

--Inputs here: 
DECLARE @StartDate datetime; 
DECLARE @EndDate datetime; 
SET @StartDate = '2010-1-5 5:00PM'; 
SET @EndDate = GETDATE(); 

--Procedure here: 
    WITH RecursiveRowGenerator (Row#, Iteration) AS (
     SELECT 1, 1 
     UNION ALL 
     SELECT Row# + Iteration, Iteration * 2 
     FROM RecursiveRowGenerator 
     WHERE Iteration * 2 < CEILING(SQRT(DATEDIFF(MONTH, @StartDate, @EndDate)+1)) 
     UNION ALL 
     SELECT Row# + (Iteration * 2), Iteration * 2 
     FROM RecursiveRowGenerator 
     WHERE Iteration * 2 < CEILING(SQRT(DATEDIFF(MONTH, @StartDate, @EndDate)+1)) 
    ) 
    , SqrtNRows AS (
     SELECT * 
     FROM RecursiveRowGenerator 
     UNION ALL 
     SELECT 0, 0 
    ) 
SELECT TOP(DATEDIFF(MONTH, @StartDate, @EndDate)+1) 
     DATEADD(month, DATEDIFF(month, 0, @StartDate) + A.Row# * POWER(2,CEILING(LOG(SQRT(DATEDIFF(MONTH, @StartDate, @EndDate)+1))/LOG(2))) + B.Row#, 0) Row# 
    FROM SqrtNRows A, SqrtNRows B 
ORDER BY A.Row#, B.Row#; 
+0

是这个工程.. – 2010-11-15 04:40:26

1

---这里是一个版本,通常获得用于会计目的月份结束日期

DECLARE @StartDate datetime; 
DECLARE @EndDate datetime; 
SET @StartDate = '2010-1-1'; 
SET @EndDate = '2020-12-31'; 
--Procedure here: 





WITH RecursiveRowGenerator (Row#, Iteration)        
AS (  SELECT 1, 1   
UNION ALL   
SELECT Row# + Iteration, Iteration * 2   
    FROM RecursiveRowGenerator   
    WHERE Iteration * 2 < CEILING(SQRT(DATEDIFF(MONTH, @StartDate, @EndDate)+1)) 
    UNION ALL  SELECT Row# + (Iteration * 2), Iteration * 2 
      FROM RecursiveRowGenerator   
      WHERE Iteration * 2 < CEILING(SQRT(DATEDIFF(MONTH, @StartDate, @EndDate)+1))  ) 
       , SqrtNRows AS (  SELECT *   FROM RecursiveRowGenerator   
UNION ALL  SELECT 0, 0  ) 
SELECT TOP(DATEDIFF(MONTH, @StartDate, @EndDate)+1)   
      DateAdd(d,-1,DateAdd(m,1, DATEADD(month, DATEDIFF(month, 0, @StartDate) + A.Row# * POWER(2,CEILING(LOG(SQRT(DATEDIFF(MONTH, @StartDate, @EndDate)+1))/LOG(2))) + B.Row#, 0) )) 
Row# FROM SqrtNRows A, SqrtNRows B ORDER BY A.Row#, B.Row#; 
13

天哪人采用“计数递归CTE”或“rCTE”是...不好或比使用循环更糟。请参阅下面的文章,为什么我这么说。

http://www.sqlservercentral.com/articles/T-SQL/74118/

这里做到这一点没有任何RBAR包括计数rCTE的“隐藏RBAR”的一种方式。下面

--===== Declare and preset some obviously named variables 
DECLARE @StartDate DATETIME, 
     @EndDate DATETIME 
; 
SELECT @StartDate = '2010-01-14', --We'll get the month for both of these 
     @EndDate = '2020-12-05' --dates and everything in between 
; 
WITH 
cteDates AS 
(--==== Creates a "Tally Table" structure for months to add to start date 
    -- calulated by the difference in months between the start and end date. 
    -- Then adds those numbers to the start of the month of the start date. 
SELECT TOP (DATEDIFF(mm,@StartDate,@EndDate) + 1) 
     MonthDate = DATEADD(mm,DATEDIFF(mm,0,@StartDate) 
        + (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1),0) 
    FROM sys.all_columns ac1 
    CROSS JOIN sys.all_columns ac2 
) 
--===== Slice each "whole month" date into the desired display values. 
SELECT [Year] = YEAR(MonthDate), 
     [Month] = MONTH(MonthDate) 
    FROM cteDates 
; 
+0

我喜欢你这样做的方法,但是最后通过调用MonthDate列的YEAR()和MONTH()函数,还没有RBAR? – reverendlarry 2012-09-21 02:52:34

+1

在幕后,T-SQL中的所有内容实际上都基于一种或另一种形式的循环,因此它们都符合“RBR”的要求。既然我是造就这句话的人,那么“RBAR”意味着什么......RBAR被发音为“ree-bar”,是“通过激励行排”的“现代主义”。该术语意味着任何需要更多资源的代码方法,或者由于其逐行性质而导致更长的运行时间,即使代码实际上是“基于集合的”代码。由于SQL Server的大多数内在功能都是以机器语言速度运行的,所以我不得不说:“不......这不是RBAR”。 ;-) – 2013-05-05 00:42:24

+0

这里最好的答案 – MoreCoffee 2014-10-29 14:11:47

1
DECLARE @Date1 DATE 
DECLARE @Date2 DATE 

SET @Date1 = '20130401' 
SET @Date2 = DATEADD(MONTH, 83, @Date1) 

SELECT DATENAME(MONTH, @Date1) "Month", MONTH(@Date1) "Month Number", YEAR(@Date1) "Year" 
INTO #Month 

WHILE (@Date1 < @Date2) 
BEGIN 
    SET @Date1 = DATEADD(MONTH, 1, @Date1) 
    INSERT INTO #Month 
    SELECT DATENAME(MONTH, @Date1) "Month", MONTH(@Date1) "Month Number", YEAR(@Date1) "Year" 
END 

SELECT * FROM #Month 
ORDER BY [Year], [Month Number] 

DROP TABLE #Month 
1

代码为七月和一月之间21 2013 15 2014范围产生的值。 我通常在SSRS报告中使用它来生成Month参数的查找值。

declare 
    @from date = '20130721', 
    @to date = '20140115'; 

with m as (
select * from (values ('Jan', '01'), ('Feb', '02'),('Mar', '03'),('Apr', '04'),('May', '05'),('Jun', '06'),('Jul', '07'),('Aug', '08'),('Sep', '09'),('Oct', '10'),('Nov', '11'),('Dec', '12')) as t(v, c)), 

y as (select cast(YEAR(getdate()) as nvarchar(4)) [v] union all select cast(YEAR(getdate())-1 as nvarchar(4))) 

select m.v + ' ' + y.v [value_field], y.v + m.c [label_field] 
from m 
cross join y 
where y.v + m.c between left(convert(nvarchar, @from, 112),6) and left(convert(nvarchar, @to, 112),6) 
order by y.v + m.c desc 

结果:

value_field  label_field 
--------------------------- 
Jan 2014  201401 
Dec 2013  201312 
Nov 2013  201311 
Oct 2013  201310 
Sep 2013  201309 
Aug 2013  201308 
Jul 2013  201307 
相关问题