2014-02-05 131 views
0

我有一個表名爲「dateadded」的列,每天我都要運行一個查詢來獲得完成8,18,28,38,48,58等幾個月的每一行。SQL選擇每10個月

這就是我今天做的方式:

select * from table 
where DATEADD(month, DATEADDED , 8) = GETDATE() 
or DATEADD(month, DATEADDED , 18) = GETDATE() 
or DATEADD(month, DATEADDED , 28) = GETDATE() ... 

但我不希望使用100「or」以上。 有沒有更好的方法來做到這一點?

+2

因此,您希望所有行的日期添加在當天下降到與今天同一天,但8個月前,18個月前等。回來多遠?什麼是你桌子上最早的日子? –

+0

不是你的問題的答案,但它應該是'DATEADD(datepart,number,date)' –

+0

我必須使用表的早期日期來知道多遠(今天是1999-02-01,但它可以換)。 – Antonio

回答

1

你可以嘗試這樣的:

SELECT * 
FROM  table 
WHERE  DATEDIFF(month, DATEADDED , GETDATE()) % 10 = 8 
    AND  DATEDIFF(month, DATEADDED , GETDATE()) < 100 -- ignore more than 100 months old 

,並使用DATEDIFF()功能,給你一個月的偏移量,飼料,在一個模運算符找到可接受的偏移。

+0

時間不要緊。他們都是00:00:00.000 – Antonio

+3

@Antonio他們是爲你*,但他們可能不會爲另一位讀者試圖解決同樣的問題,所以指出它很重要。與關於sargability的部分相同 - 如果存在,則不會在DATEADDED上使用索引。 –

5

這可以利用DATEADDED列中的索引,如果存在,或者應該在未來添加索引。針對列執行DATEDIFF()等功能的解決方案直接阻止SQL Server甚至考慮索引,並強制它掃描(缺少任何其他謂詞來限制搜索空間)。

CREATE TABLE #x(ID INT IDENTITY(1,1), DATEADDED DATETIME); 

INSERT #x(DATEADDED) VALUES 
('20130605 04:56'), -- 8 months ago 
('20120805 23:59'), -- 18 months ago 
('20111005 14:36'), -- 28 months ago 
('20101105 04:23'); -- should not be found 

;WITH cte AS 
(
    SELECT TOP (DATEDIFF(MONTH,'19990201',GETDATE())/10+1) 
    d = CONVERT(DATE,DATEADD(MONTH,-((number*10)-2),GETDATE())) 
    FROM master.dbo.spt_values WHERE [type] = N'P' AND number > 0 ORDER BY number 
) 
SELECT x.ID, x.DATEADDED 
FROM #x AS x 
INNER JOIN cte 
ON x.DATEADDED >= cte.d 
AND x.DATEADDED < DATEADD(DAY,1,cte.d); 
+4

請解釋downvote。 –