2010-11-15 35 views
6

Tôi cần chọn trả về Tháng và năm Trong phạm vi ngày được chỉ định mà tôi sẽ nhập năm bắt đầu và tháng và lựa chọn sẽ trả về tháng và năm kể từ ngày tôi đầu vào cho đến ngày hôm nay.t-sql chọn nhận được tất cả các tháng trong một phạm vi năm

Tôi biết tôi có thể làm điều này trong một vòng lặp nhưng tôi đã tự hỏi nếu nó có thể làm điều này trong một loạt lựa chọn?

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

v.v.

+0

sql server 2008 –

Trả lời

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

bạn có thể làm như sau

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

cách bạn sẽ sử dụng "tiêu chuẩn thích hợp" bạn có thể hiển thị ví dụ ... như tất cả các ngày 2009-12 đến ngày hôm nay –

3

Bạn có thể sử dụng một cái gì đó như thế này: http://blogs.msdn.com/b/sqlazure/archive/2010/09/16/10063301.aspx

Để tạo tương đương với một bảng số sử dụng phạm vi ngày.

Nhưng bạn có thể làm rõ đầu vào và đầu ra của mình không?

Bạn có muốn nhập ngày bắt đầu, ví dụ: '2010-5-1' và ngày kết thúc, ví dụ: '2010-8-1' và có trả lại hàng tháng giữa hai ngày không? Bạn có muốn bao gồm tháng bắt đầu và tháng kết thúc hay loại trừ chúng không?

Dưới đây là một số mã mà tôi đã viết sẽ nhanh chóng tạo ra kết quả bao gồm hàng tháng giữa hai ngày.

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

Có làm việc này .. –

1

--- Đây là một phiên bản mà được những ngày tháng cuối thường được sử dụng cho mục đích kế toán

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

folks Gosh ... sử dụng một "đếm đệ quy CTE" hoặc "rCTE" là như xấu hoặc tệ hơn sử dụng vòng lặp. Vui lòng xem bài viết sau để biết lý do tôi nói điều đó.

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

Dưới đây là một cách để làm điều đó mà không cần bất kỳ RBAR bao gồm cả "ẩn RBAR" của một rCTE đếm.

--===== 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

Tôi thích phương pháp của bạn để làm điều đó, nhưng cuối cùng thì vẫn chưa có RBAR bằng cách gọi hàm NĂM() và MONTH() trên cột MonthDate? – reverendlarry

+1

Phía sau hậu trường, mọi thứ trong T-SQL thực sự dựa trên một vòng lặp của một dạng này hay dạng khác để tất cả đều đủ điều kiện là "RBR". Vì tôi là người đã đặt ra cụm từ, đây là những gì "RBAR" đã có ý nghĩa ...RBAR được phát âm là "ree-bar" và là "Modenism" cho "Row By Agonizing Row". Thuật ngữ này có nghĩa là bất kỳ phương thức mã nào đòi hỏi nhiều tài nguyên hơn hoặc gây ra các lần chạy dài hơn vì tính chất hàng-by-hàng của nó ngay cả khi mã thực sự là "được đặt dựa trên" mã. Vì hầu hết các chức năng nội tại của SQL Server hoạt động ở tốc độ ngôn ngữ máy, tôi phải nói, "Không ... đây không phải là RBAR". ;-) –

+0

câu trả lời hay nhất tại đây – MoreCoffee

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

Mã dưới đây tạo ra giá trị cho phạm vi giữa 21 tháng 7 năm 201315 tháng 1 năm 2014. Tôi thường sử dụng báo cáo này trong các báo cáo SSRS để tạo giá trị tra cứu cho tham số Tháng.

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 

Kết quả:

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 
Các vấn đề liên quan