在SQL服务器上获取上个月的logging
我想根据我的数据库表[成员]字段“date_created”得到上个月的logging。
什么是SQL来做到这一点?
澄清,上个月 – 2009年1月8日至31/8/2009
如果今天是2010年1月3日,我将需要获取2009年1月12日至2009年12月31日的logging。
SELECT * FROM Member WHERE DATEPART(m, date_created) = DATEPART(m, DATEADD(m, -1, getdate())) AND DATEPART(yyyy, date_created) = DATEPART(yyyy, DATEADD(m, -1, getdate()))
你需要检查月份和年份。
所有现有(工作)答案都有两个问题之一:
- 他们将忽略正在search的列的索引
- 意志(可能)select不是有意的数据,默默地破坏你的结果。
1.忽略指数:
大多数情况下,当一个被search的列有一个函数被调用时(包括隐含的,就像CAST
),优化器必须忽略列上的索引并search每个logging。 这里有一个简单的例子:
我们正在处理时间戳,大多数RDBMS倾向于将这些信息存储为某种types的增加值,通常是long
或BIGINTEGER
毫秒/纳秒的计数。 当前时间因此看起来/被存储如下:
1402401635000000 -- 2014-06-10 12:00:35.000000 GMT
你没有在那里看到'年'的价值( '2014'
),是吗? 事实上,有一些复杂的math来回翻译。 因此,如果您在search列中调用任何提取/date部分函数,则服务器必须执行所有这些计算,以确定是否可以将其包含在结果中。 在小桌子上,这不是一个问题,但是随着所选行数的减less,这成为越来越大的漏点。 那么在这种情况下,你是在第二次询问MONTH
…呃,你得到了这张照片。
2.意外数据:
根据特定版本的SQL Server和列数据types,使用BETWEEN
(或类似的上限范围: <=
) 可能会导致select错误的数据 。 本质上,您最终可能会包含“下一天”午夜的数据,或排除“当前”当天logging的某些部分。
你应该做什么:
所以我们需要一种对数据安全的方法,并使用索引(如果可行)。 正确的方法是这样的forms:
WHERE date_created >= @startOfPreviousMonth AND date_created < @startOfCurrentMonth
考虑到只有一个月,可以很容易地用@startOfPreviousMonth
代替/派生:
DATEADD(month, -1, @startOCurrentfMonth)
如果您需要在服务器中获取当前月份的起始date,可以通过以下方式进行操作:
DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
这里有一个简短的解释。 最初的DATEDIFF(...)
将得到当前时代的开始( 0001-01-01
– AD,CE,不pipe),基本上返回一个大整数之间的区别。 这是本月开始的月数。 然后我们把这个数字加到这个月的开始时代。
因此,您的完整脚本可以/应该看起来类似于以下内容:
DECLARE @startOfCurrentMonth DATETIME SET @startOfCurrentMonth = DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0) SELECT * FROM Member WHERE date_created >= DATEADD(month, -1, @startOfCurrentMonth) -- this was originally misspelled AND date_created < @startOfCurrentMonth
所有的date操作因此只能在一个值上执行一次; 优化器可以自由使用索引,并且不会包含不正确的数据。
添加到目前为止提供的选项根本不会使用你的索引。
像这样的东西会做的伎俩,并使用表上的索引(如果存在)。
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = dateadd(mm, -1, getdate()) SET @StartDate = dateadd(dd, datepart(dd, getdate())*-1, @StartDate) SET @EndDate = dateadd(mm, 1, @StartDate) SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = DATEADD(mm, DATEDIFF(mm,0,getdate())-1, 0) SET @EndDate = DATEADD(mm, 1, @StartDate) SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate
升级到mrdenny的解决scheme,这种方式你正好从上个月YYYY-MM-01
一种方法是使用DATEPARTfunction:
select field1, field2, fieldN from TABLE where DATEPART(month, date_created) = 4 and DATEPART(year, date_created) = 2009
将在四月份返回所有date。 对于上个月(即,当前月份之前),您也可以使用GETDATE和DATEADD :
select field1, field2, fieldN from TABLE where DATEPART(month, date_created) = (DATEPART(month, GETDATE()) - 1) and DATEPART(year, date_created) = DATEPART(year, DATEADD(m, -1, GETDATE()))
select * from [member] where DatePart("m", date_created) = DatePart("m", DateAdd("m", -1, getdate())) AND DatePart("yyyy", date_created) = DatePart("yyyy", DateAdd("m", -1, getdate()))
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0) SET @EndDate = dateadd(dd, -1, DATEADD(mm, 1, @StartDate)) SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate
另一个升级到mrdenny的解决scheme。
它给出了确切的前一个月的最后一天。
declare @PrevMonth as nvarchar(256) SELECT @PrevMonth = DateName( month,DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0)) + '-' + substring(DateName( Year, getDate() ) ,3,4)
上个月考虑,直到本月的最后一天。 31/01/2016这里的最后一天是1月31日,这和过去30天不一样。
SELECT CONVERT(DATE, DATEADD(DAY,-DAY(GETDATE()),GETDATE()))
在最近一个月的Sql服务器上:
select * from tablename where order_date > DateAdd(WEEK, -1, GETDATE()+1) and order_date<=GETDATE()
DECLARE @curDate INT = datepart( Month,GETDATE()) IF (@curDate = 1) BEGIN select * from Featured_Deal where datepart( Month,Created_Date)=12 AND datepart(Year,Created_Date) = (datepart(Year,GETDATE())-1) END ELSE BEGIN select * from Featured_Deal where datepart( Month,Created_Date)=(datepart( Month,GETDATE())-1) AND datepart(Year,Created_Date) = datepart(Year,GETDATE()) END
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = dateadd(mm, -1, getdate()) SET @StartDate = dateadd(dd, datepart(dd, getdate())*-1, @StartDate) SET @EndDate = dateadd(mm, 1, @StartDate) set @StartDate = DATEADD(dd, 1 , @StartDate)
WHERE date_created >= DATEADD(MONTH, DATEDIFF(MONTH, 31, CURRENT_TIMESTAMP), 0) AND date_created < DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
我来自Oracle env,我会在Oracle中这样做:
select * from table where trunc(somedatefield, 'MONTH') = trunc(sysdate -INTERVAL '0-1' YEAR TO MONTH, 'MONTH')
想法:我正在执行上个月的预定报告(从第1天到本月的最后一天,没有窗口)。 这可能是索引不友好,但甲骨文有快速的date处理。 MS SQL有没有类似的简单方法? 分别比较年份和月份的答案似乎对甲骨文人来说是愚蠢的。
您可以使用此查询获取上个月的logging
SELECT * FROM dbo.member d WHERE CONVERT(DATE,date_created,101)> = CONVERT(DATE,DATEADD(m,datediff(m,0,current_timestamp)-1,0))和CONVERT(DATE,date_created,101)< CONVERT(DATE,DATEADD(m,datediff(m,0,current_timestamp)-1,0),101)