我想根据我的数据库表[member]字段“ date_created”获取上个月的记录。
什么是SQL来做到这一点?
为了澄清起见,上个月-2009年1月8日至2009年8月31日
如果今天是2010年3月1日,我需要获取2009年1月12日至2009年12月31日的记录。
我想根据我的数据库表[member]字段“ date_created”获取上个月的记录。
什么是SQL来做到这一点?
为了澄清起见,上个月-2009年1月8日至2009年8月31日
如果今天是2010年3月1日,我需要获取2009年1月12日至2009年12月31日的记录。
DATEDIFF(month, date_created, GETDATE()) = 1
呢 那还行吗?
Answers:
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()))
您需要检查月份和年份。
SELECT * FROM Member WHERE DATEPART(m, date_created) = DATEPART(m, DATEADD(m, -1, getdate())) AND DATEPART(yy, date_created) = DATEPART(yy, DATEADD(m, -1, getdate()))
效果很好
所有现有的(有效的)答案都具有以下两个问题之一:
1.忽略的索引:
在大多数情况下,当要搜索的列具有调用的函数时(包括隐式的,如for CAST
),优化器必须忽略该列上的索引并搜索每条记录。这是一个简单的例子:
我们正在处理时间戳,大多数RDBMS倾向于以某种递增的值(通常为1毫秒long
或BIGINTEGER
毫秒)存储此信息。因此,当前时间看起来/存储如下:
1402401635000000 -- 2014-06-10 12:00:35.000000 GMT
您没有在其中看到“年”值('2014'
),对吗?实际上,有很多复杂的数学来回翻译。因此,如果您在搜索列中调用任何提取/日期部分函数,则服务器必须执行所有数学运算,才能弄清楚是否可以将其包括在结果中。在小型表上,这不是问题,但是随着所选行的百分比减少,这将变得越来越大。然后,在这种情况下,您需要第二次询问MONTH
...好了,您知道了。
2.意外数据:
取决于在SQL Server的特定版本,并且列数据类型,使用BETWEEN
(或类似的含上限范围:<=
)可能导致错误的数据被选择。本质上,您可能最终会包含“第二天”午夜以来的数据,或者排除“当前”天记录的某些部分。
您应该做什么:
因此,我们需要一种对数据安全的方法,并使用索引(如果可行)。正确的方式为:
WHERE date_created >= @startOfPreviousMonth AND date_created < @startOfCurrentMonth
鉴于只有一个月,@startOfPreviousMonth
可以很容易地用以下方法代替/派生:
DATEADD(month, -1, @startOCurrentfMonth)
如果您需要在服务器中导出当前月份的开始,则可以通过以下方法进行操作:
DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
快速解释一下。初始值DATEDIFF(...)
将获得当前时代开始之间的差异(0001-01-01
-AD,CE,等等),本质上返回一个大整数。这是几个月来的开始计数当前的月份。然后,我们将该数字添加到时代的开始,即给定月份的开始。
因此,您的完整脚本可能/应该类似于以下内容:
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
因此,所有日期运算仅对一个值执行一次;优化器可以自由使用索引,并且不会包含任何不正确的数据。
添加到目前为止提供的选项根本不会使用您的索引。
这样的事情将可以解决问题,并利用表上的索引(如果存在)。
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
一种方法是使用DATEPART函数:
select field1, field2, fieldN from TABLE where DATEPART(month, date_created) = 4
and DATEPART(year, date_created) = 2009
将返回4月的所有日期。对于上个月(即,本月之前的月份),您还可以使用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()))
WHERE
date_created >= DATEADD(MONTH, DATEDIFF(MONTH, 31, CURRENT_TIMESTAMP), 0)
AND date_created < DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
您可以通过此查询获取上个月的记录
SELECT * FROM dbo.member d
WHERE CONVERT(DATE, date_created,101)>=CONVERT(DATE,DATEADD(m, datediff(m, 0, current_timestamp)-1, 0))
and CONVERT(DATE, date_created,101) < CONVERT(DATE, DATEADD(m, datediff(m, 0, current_timestamp)-1, 0),101)
我认为接受的解决方案不是非常友好的索引,我改用以下几行
select * from dbtable where the_date >= convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120) and the_date <= dateadd(ms, -3, convert(varchar(10),DATEADD(m, 0, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120));
或者简单地(这是最好的)。
select * from dbtable where the_date >= convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120) and the_date < SELECT convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120);
一些帮助
-- Get the first of last month
SELECT convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120);
-- Get the first of current month
SELECT convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120);
--Get the last of last month except the last 3milli seconds. (3miliseconds being used as SQL express otherwise round it up to the full second (SERIUSLY MS)
SELECT dateadd(ms, -3, convert(varchar(10),DATEADD(m, 0, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120));
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)
如果您正在寻找上个月,请尝试此操作,
SELECT
FROM #emp
WHERE DATEDIFF(MONTH,CREATEDDATE,GETDATE()) = 1
如果您正在寻找上个月,请尝试此操作,
SELECT
FROM #emp
WHERE DATEDIFF(day,CREATEDDATE,GETDATE()) between 1 and 30
一个对我有用的简单查询是:
从表中选择*,其中DATEADD(month,1,DATEFIELD)> = getdate()