2010-11-15 15 views
6

Potrzebuję wybrać, aby zwrócić miesiąc i rok w określonym zakresie dat, w którym chciałbym wprowadzić rok i miesiąc rozpoczęcia i wybrałby powrót miesiąc i rok od daty I wejście do dziś.t-sql wybierz, aby uzyskać wszystkie miesiące w zakresie lat

Wiem, że mogę to zrobić w pętli, ale zastanawiałem się, czy można to zrobić w serii wybiera?

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

i tak dalej.

+0

SQL Server 2008 –

Odpowiedz

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

można wykonać następujące czynności

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

w jaki sposób korzystać z "odpowiednich kryteriów" można pokazać przykład ... jak wszystkich dat od 2009-12 do dziś –

3

Można użyć coś takiego: http://blogs.msdn.com/b/sqlazure/archive/2010/09/16/10063301.aspx

Aby wygenerować równowartość tabeli liczby osób korzystających z zakresy dat.

Ale czy mógłbyś wyjaśnić swoje wejścia i wyjścia?

Czy chcesz wprowadzić datę początkową, na przykład '2010-5-1' i datę końcową, na przykład '2010-8-1' i czy będzie ona zwracana co miesiąc między tymi dwoma? Czy chcesz uwzględnić miesiąc początkowy i końcowy lub wykluczyć je?

Oto kod, który napisałem, który szybko wygeneruje wynik obejmujący każdy miesiąc między dwiema datami.

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

Tak to działa .. –

1

--- Tutaj jest wersja, że ​​dostaje daty koniec miesiąca zazwyczaj wykorzystywane do celów księgowych

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

Gosh ludzie ... wykorzystujące „Liczenie rekurencyjnej CTE” lub „rCTE” jest złe lub gorsze niż użycie pętli. Zapoznaj się z następującym artykułem, dlaczego tak mówię.

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

Oto jeden ze sposobów, aby to zrobić bez RBAR tym „ukrytym RBAR” z rCTE liczenia. poniżej

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

Podoba mi się twoja metoda robienia tego, ale na końcu nie ma jeszcze RBAR przez wywołanie funkcji YEAR() i MONTH() w kolumnie MonthDate? – reverendlarry

+1

Za kulisami, wszystko w T-SQL jest oparte na pętli jednej lub drugiej formy, więc wszystko kwalifikuje się jako "RBR". Ponieważ jestem facetem, który wymyślił to wyrażenie, oto co "RBAR" ma znaczyć ...RBAR wymawia się "ree-bar" i jest "modenizmem" w "Row By Agonizing Row". Termin ten oznacza dowolną metodę kodu wymagającą więcej zasobów lub powodującą dłuższe działanie z powodu jej charakteru "rząd po rzędzie", nawet jeśli kod jest w rzeczywistości zbiorem "opartym na zestawie". Ponieważ większość wewnętrznych funkcji SQL Servera działa z prędkością języka maszyny, musiałbym powiedzieć: "Nie ... to nie jest RBAR". ;-) –

+0

najlepsza odpowiedź tutaj – 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

kod generuje wartości dla zakresu między 21 lipca 2013 i 15 stycznia 2014. Zwykle używam go w raportach SSRS do generowania wartości wyszukiwania dla parametru Miesiąc.

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 

Wyniki:

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 
Powiązane problemy