获取SQL Server上个月的记录

时间:2009-09-15 03:38:49

标签: sql sql-server tsql

我想根据我的db table [member]字段“date_created”获取上个月的记录。

这是做什么的SQL?

澄清, 上个月 - 2009年1月8日至2009年8月31日

如果今天是2010年3月1日,我需要获取2009年1月12日至2009年12月31日的记录。

23 个答案:

答案 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. 他们将忽略被搜索列的索引
  2. 意志(可能)选择不打算的数据,静默地破坏您的结果。
  3. <强> 1。忽略指数:

    在大多数情况下,当被搜索的列具有一个被调用的函数(包括隐式,如CAST)时,优化器必须忽略列上的索引并搜索每个记录。这是一个简单的例子:

    我们正在处理时间戳,并且大多数RDBMS倾向于将此信息存储为某种增加值,通常为{/ 1}}或long毫安/纳秒。因此,当前时间看起来像这样存储:

    BIGINTEGER

    你没有在那里看到'年'值(1402401635000000 -- 2014-06-10 12:00:35.000000 GMT ),对吗?事实上,来回翻译需要相当复杂的数学。因此,如果您在搜索列上调用任何提取/日期部分函数,​​则服务器必须执行所有数学计算,以确定是否可以将其包含在结果中。在小桌子上这不是问题,但随着所选行的百分比减少,这变得越来越大。然后在这种情况下,你第二次这样做是为了询问'2014' ......好吧,你得到的照片。

    <强> 2。意外数据:

    取决于特定版本的SQL Server和列数据类型,使用MONTH(或类似的包含上限范围:BETWEENcan 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月返回所有日期。对于上个月(即当前月份),您也可以使用GETDATEDATEADD

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()