我想根据我的db table [member]字段“date_created”获取上个月的记录。
这是做什么的SQL?
澄清, 上个月 - 2009年1月8日至2009年8月31日
如果今天是2010年3月1日,我需要获取2009年1月12日至2009年12月31日的记录。
答案 0 :(得分:92)
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()))
您需要检查月份和年份。
答案 1 :(得分:76)
所有现有(工作)答案都有两个问题之一:
<强> 1。忽略指数:
在大多数情况下,当被搜索的列具有一个被调用的函数(包括隐式,如CAST
)时,优化器必须忽略列上的索引并搜索每个记录。这是一个简单的例子:
我们正在处理时间戳,并且大多数RDBMS倾向于将此信息存储为某种增加值,通常为{/ 1}}或long
毫安/纳秒。因此,当前时间看起来像这样存储:
BIGINTEGER
你没有在那里看到'年'值(1402401635000000 -- 2014-06-10 12:00:35.000000 GMT
),对吗?事实上,来回翻译需要相当复杂的数学。因此,如果您在搜索列上调用任何提取/日期部分函数,则服务器必须执行所有数学计算,以确定是否可以将其包含在结果中。在小桌子上这不是问题,但随着所选行的百分比减少,这变得越来越大。然后在这种情况下,你第二次这样做是为了询问'2014'
......好吧,你得到的照片。
<强> 2。意外数据:
取决于特定版本的SQL Server和列数据类型,使用MONTH
(或类似的包含上限范围:BETWEEN
)can result in the wrong data being selected。从本质上讲,您可能最终会在“下一天”的午夜包含数据,或者排除“当前”日记录的某些部分。
应该做什么:
因此,我们需要一种对我们的数据安全的方法,并且将使用索引(如果可行)。那么正确的方式是:
<=
鉴于只有一个月,WHERE date_created >= @startOfPreviousMonth AND date_created < @startOfCurrentMonth
可以很容易地替换/派生:
@startOfPreviousMonth
如果您需要在服务器中派生当前月初,可以通过以下方式完成:
DATEADD(month, -1, @startOCurrentfMonth)
这里有一个简短的解释。初始DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
将获得当前时代的开始(DATEDIFF(...)
- AD,CE,等等)之间的差异,基本上返回一个大整数。这是当前月开始的月数。然后我们将这个数字添加到时代的开始,这是在给定月份的开始。
因此,您的完整脚本可能/应该类似于以下内容:
0001-01-01
因此,所有日期操作仅在一个值上执行一次;优化器可以自由使用索引,并且不会包含不正确的数据。
答案 2 :(得分:12)
添加到目前为止提供的选项根本不会使用您的索引。
这样的东西可以解决问题,并利用表上的索引(如果存在)。
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
答案 3 :(得分:9)
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的解决方案,这样你就可以从YYYY-MM-01上个月获得
答案 4 :(得分:2)
一种方法是使用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()))
答案 5 :(得分:2)
declare @PrevMonth as nvarchar(256)
SELECT @PrevMonth = DateName( month,DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0)) +
'-' + substring(DateName( Year, getDate() ) ,3,4)
答案 6 :(得分:2)
上个月考虑到本月的最后一天。 2016年1月31日这个月的最后一天将是1月31日,这与过去30天不相似。
SELECT CONVERT(DATE, DATEADD(DAY,-DAY(GETDATE()),GETDATE()))
答案 7 :(得分:1)
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()))
答案 8 :(得分:1)
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的解决方案 它也给出了上个月的确切最后一天。
答案 9 :(得分:1)
WHERE
date_created >= DATEADD(MONTH, DATEDIFF(MONTH, 31, CURRENT_TIMESTAMP), 0)
AND date_created < DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
答案 10 :(得分:1)
我来自Oracle环境,我会在Oracle中这样做:
select * from table
where trunc(somedatefield, 'MONTH') =
trunc(sysdate -INTERVAL '0-1' YEAR TO MONTH, 'MONTH')
想法:我正在运行上个月的预定报告(从第1天到第1天的最后一天,没有窗口)。这可能是索引不友好,但Oracle无论如何都有快速处理日期。 在MS SQL中是否有类似的简单和简短的方法?分别比较年份和月份的答案对Oracle员工来说似乎很愚蠢。
答案 11 :(得分:1)
您可以使用此查询获取上个月的记录
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)
答案 12 :(得分:1)
仅获取当月记录的SQL查询
SELECT * FROM CUSTOMER
WHERE MONTH(DATE) = MONTH(CURRENT_TIMESTAMP) AND YEAR(DATE) = YEAR(CURRENT_TIMESTAMP);
答案 13 :(得分:0)
这是我所做的,所以我可以把它放在一个视图中:
ALTER view [dbo].[MyView] as
with justdate as (
select getdate() as rightnow
)
, inputs as (
select dateadd(day, 1, EOMONTH(jd.rightnow, -2)) as FirstOfLastMonth
,dateadd(day, 1, EOMONTH(jd.rightnow, -1)) as FirstOfThisMonth
from justdate jd
)
SELECT TOP 10000
[SomeColumn]
,[CreatedTime]
from inputs i
join [dbo].[SomeTable]
on createdtime >= i.FirstOfLastMonth
and createdtime < i.FirstOfThisMonth
order by createdtime
;
请注意,我特意运行了一次 getdate()
。
答案 14 :(得分:0)
SELECT * FROM Member WHERE month(date_created) = month(NOW() - INTERVAL 1 MONTH);
答案 15 :(得分:0)
我认为公认的解决方案不是非常友好的索引 我改用以下几行
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));
答案 16 :(得分:0)
如果要查找上个月的数据:
date(date_created)>=date_sub(date_format(curdate(),"%Y-%m-01"),interval 1 month) and
date(date_created)<=date_sub(date_format(curdate(),'%Y-%m-01'),interval 1 day)
当年份更改时,这也将起作用。它也可以在MySQL上运行。
答案 17 :(得分:0)
一个对我有用的简单查询是:
从DATEADD(month,1,DATEFIELD)> = getdate()的表中选择*
答案 18 :(得分:0)
如果您正在寻找上个月,请尝试尝试
SELECT
FROM #emp
WHERE DATEDIFF(MONTH,CREATEDDATE,GETDATE()) = 1
如果您正在寻找上个月,请尝试尝试
SELECT
FROM #emp
WHERE DATEDIFF(day,CREATEDDATE,GETDATE()) between 1 and 30
答案 19 :(得分:0)
我修复类似问题的方法是将Month添加到 SELECT 部分
Month DATEADD(day,Created_Date,'1971/12/31') As Month
并且我添加了 WHERE 语句
Month DATEADD(day,Created_Date,'1971/12/31') = month(getdate())-1
答案 20 :(得分:0)
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)
答案 21 :(得分:0)
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
答案 22 :(得分:0)
在过去一个月的Sql server中:
select * from tablename
where order_date > DateAdd(WEEK, -1, GETDATE()+1) and order_date<=GETDATE()