2011-10-27 100 views
0

我想兩個日期之間選擇的數據之間,沒有一天SQL Server 2008中選擇數據只月份和年份

輸入例如:

起始月份:9,開始年度:2011
月末: 3,結束年份:2012

我認爲有兩種方法可以做到這一點。

第一個是轉換開始月份和開始年份,如2011-09-01,並將最後日期轉換爲2012-03-31,但這需要計算結束月份的最後一天。獲得了這些數據,我們可以使用的WHERE子句的BEETWEN功能(但是,是轉換功能可靠嗎?)

第二種解決方案是在下面的代碼使用DATEPART功能,如:

我試着解釋:如果結束年份等於最初一年,則月份必須在開始月份和結束月份之間;否則,如果最後幾個月如果與最初和最後一年不同,那麼最終的月份會大於最初的年份,我會把所有的事情放在一起;否則如果最後一年,該月必須小於或等於最後一個月,如果最初一年,月份必須大於或等於最後一個月

您能幫我以最好的方式做到這一點嗎?是正確的,我採用的解決方案?

declare @IndDebitoCredito bit,@ProgTributo int,@mi as integer,@ai as integer,@mf as integer,@af as integer,@IDAnagrafica varchar(5) 
select @mi = 01,@ai = 2011,@mf = 12,@af = 2011,@IDAnagrafica = 'DELEL',@IndDebitoCredito = 1 
select distinct rrd.IDTributo 
    from TBWH_Delega d 
    --inner join TBWH_SezioneDelega sd on d.IDDelega = sd.IDDelega 
    inner join TBWH_Rigo rd on rd.IDDelega = d.IDDelega 
    inner join TBWH_RataRigo rrd on rrd.IDRigo = rd.IDRigo 
    where 
    (
     DATEPART(MM,d.DataDelega)<[email protected] and 
     DATEPART(MM,d.DataDelega)>[email protected] and 
     DATEPART(YYYY,d.DataDelega)[email protected] and 
     @af = @ai 
    ) 
    OR 
    (
     --anno finale magg. anno iniziale 
     @af > @ai AND 
     ( 
      ( -- delega nell'intervallo 
       DATEPART(YYYY,d.DataDelega)<@af AND 
       DATEPART(YYYY,d.DataDelega)>@ai 
       -- DATEPART(MM,d.DataDelega)>[email protected] 
      ) 
      OR 
      ( -- delega limite destro 
       DATEPART(YYYY,d.DataDelega)[email protected] AND 
       DATEPART(MM,d.DataDelega)<[email protected] 
      ) 
      OR 
      ( -- delega limite sinistro 
       DATEPART(YYYY,d.DataDelega)[email protected] AND 
       DATEPART(MM,d.DataDelega)>[email protected] 
      ) 
     ) 
    ) 

GO

+3

起初,我以爲最終的GO是爲我們:「這裏的是,現在的問題... GO!」 :) –

回答

1

您是WAY這過於複雜。你真的只需要兩個比較:

  • 是月份和年份之後或等於初始值?
  • 是之前的月份還是等於最終值?

嘗試:在使用設置DateField列的表達式

SELECT * 
FROM MyTable 
WHERE Datefield BETWEEN 
    CAST(@mi as varchar) + '/1/' + CAST(@ai as varchar) 
    -- first of first month 
    AND 
    DATEADD(DAY, -1, (DATEADD(Month, + 1, (CAST(@mf as varchar) + '/1/' + CAST(@af as varchar))))) 
    -- Last day or final month 
+0

我建議使用ISO-8601標準日期格式:'YYYYMMDD',因爲這是獨立的SQL Server中的任何語言/區域設置 - 在我的服務器上,'10/1/1'將被解釋爲第10 2011年1月,例如..... –

+1

@marc_s - 好點,這將是區域特定的,如書面 – JNK

+0

由於區域設置,我無法測試這個,但它是否會包含上個月最後一天的行?是的,如果'DateField'是一個日期而不是一個日期時間。或者如果時間部分始終設置爲午夜。 –

0
SELECT * 
    FROM Table 
WHERE DateField 
     BETWEEN CONVERT(DATE, CONVERT(CHAR(4), @ai) + RIGHT('00' + CONVERT(VARCHAR(2), @mi), 2) + '01', 112) 
      AND DATEADD(DD, -1, DATEADD(MM, 1, CONVERT(DATE, CONVERT(CHAR(4), @af) + RIGHT('00' + CONVERT(VARCHAR(2), @mf), 2) + '01', 112))) 

避免的,因爲它使查詢不SARGable

2

你的第一個解決方案几乎就在那裏,但比它需要的更復雜,反正也不行。它將錯過最後一個月的最後一天的任何行。

您可以添加一個月到end month,然後在每個月的第一個月使用BETWEEN。例如。

start month: 9 , start year: 2011 end month: 3, end year: 2012

BETWEEN '2011-09-01' AND '2012-04-01'

,或者作爲JNK指出,這會更好:

DataDelega >= '2011-09-01' AND DataDelega < '2012-04-01'

你需要一些邏輯添加到處理end month是十二月,但這看起來是最簡單的做法。

+0

除了「BETWEEN」包含在內,所以這將包括「2012年4月1日」。 – JNK

+0

你是對的 - 它將包含來自'2012-04-01 00:00:000''的任何行。沒有看到有關數據,我不知道這是否有問題。 –

+0

他在這個問題中說,他只想包括截至最後一個月的數據。 – JNK

0

我會用:

WHERE DateToCheck >=    --- first day of StartMonth 
      DATEADD(mm, @StartMonth-1, 
        DATEADD(yy, @StartYear-2000, '2000-01-01') 
       ) 
    AND DateToCheck <    --- first day of next month (after EndMonth) 
      DATEADD(mm, @EndMonth, 
        DATEADD(yy, @EndYear-2000, '2000-01-01') 
       ) 
0
DECLARE @mi INT 
    , @ai INT 
    , @mf INT 
    , @af INT 
SELECT @mi = 01 
     , @ai = 2011 
     , @mf = 12 
     , @af = 2011 

--local variables to hold dates 
DECLARE @i DATETIME 
    , @f DATETIME 

--build strings to represent dates in YYYYMMDD format 
--add a month to the @f date 
SELECT @i = CONVERT(VARCHAR(4), @ai) + RIGHT('0' + CONVERT(VARCHAR(2), @mi), 
               2) + '01' 
     , @f = DATEADD(month, 1, 
        CONVERT(VARCHAR(4), @af) + RIGHT('0' 
                 + CONVERT(VARCHAR(2), @mf), 
                 2) + '01') 

--select data where date >= @i, and < @f 
SELECT * 
FROM MyTable 
WHERE DateField >= @i 
     AND DateField < @f