2016-06-20 1322 views
1

我需要查询SQL的数据落入上个月的日期。我以为我使用正确的查询逻辑,但我没有得到任何结果,我知道有结果。代码片段是这样的:SQL查询减1个月

MONTH(n.JOIN_DATE) = DATEADD(month, - 1, GETDATE()) 

这给我没有结果,我需要得到任何有上个月加入日期的人。我错过了什么?

+1

你能显示你的完整查询吗? –

+0

还有一些示例数据会很好。 –

+4

'MONTH()'返回一个月份号码。 'DATEADD()'返回一个日期。一个月永远不会等同于一个日期。 –

回答

1

MONTH(n.JOIN_DATE)将仅返回月份的数值(例如:115)。

DATEADD(MONTH, -1, GETDATE())将简单地从当前日期减去一个月。它仍然是DATETIME格式。

你可能会寻找:

MONTH(n.JOIN_DATE) = MONTH(DATEADD(MONTH, -1, GETDATE())) 
3

使用此:

MONTH(n.JOIN_DATE) = MONTH(DATEADD(month, - 1, GETDATE())) 

你需要与苹果比较苹果,所以数值比较每月在等式的两边。

在我做这件事之前,为了解决这个问题,我大量赞助@PaulL。

更新:

由于@DasBlinkenLight和马特指出,仅仅靠一个月比较敞开了大门要返回多年。一种可能的解决办法是比较几年,例如

WHERE MONTH(n.JOIN_DATE) = MONTH(DATEADD(month, - 1, GETDATE())) AND 
     YEAR(n.JOIN_DATE) = YEAR(DATEADD(month, - 1, GETDATE())) 
+0

如果数据集中存在超过1年,则会返回多年的结果。如果你还添加AND AND YEAR(n.JOIN_DATE)= YEAR(DATEADD(year,-1,GETDATE())将会解决这个问题 – Matt

1

MONTH(...)产生一个月数。您不应该将其与DATEADD返回的结果进行比较,该结果实际上是一个日期。

如果您正在寻找大家谁已经不到一个月前加入,你可以做这样的:

WHERE DATEADD(month, 1, n.JOIN_DATE) > GETDATE() 

这是考虑到今年与天为好,不仅月份。

如果您正在寻找大家谁上个月参加,在那一天没有事,你可以使用更复杂的条件:

WHERE MONTH(DATEADD(month, -1, GETDATE()) = MONTH(n.JOIN_DATE) 
    AND YEAR (DATEADD(month, -1, GETDATE()) = YEAR (n.JOIN_DATE) 

第二个条件是必要的,以避免成员之间的混淆加盟上个月成员在一年或更多年前的同一个月加入。

-2

对此答案的回复是正确的。但是根据最佳实践来编写查询,这种方式会使得查询不那么可靠,因此如果您有查询,就会忽略索引。它可能会更好地写为

WHERE n.JOIN_DATE between DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) AND DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1) 

基于下面的评论我已修改查询。我想我没有深入地读过这个问题。

+0

如果我今天运行,2016-06-20,它不会返回2016- 05-02,它应该,但会返回2016-06-03,它不应该。相应地downvoted。 –

+0

返回到您的早期版本DATEADD(month,-1,GETDATE())和GETDATE()。一个返回了5/20到6/20的正确日期范围,这个返回6/1到5/31 23:59:59.000这是错误的顺序和不正确的日期我不知道什么@ DanBracuk打字是为了得到他的结果 – Matt

+0

这个问题说他想要在上个月有所下降,这是我假设的5/20范围还是我误解了? – damola

1
MONTH(n.JOIN_DATE) returns a numeric which indicate the month in date m.JOIN_DATE 
DATEADD(month, - 1, GETDATE()) returns a date which indicate date in last month. 
So, you can use this instead : 
MONTH(n.JOIN_DATE)= MONTH(DATEADD(month, - 1, GETDATE())) 
OR 
n.JOIN_DATE = DATEADD(month, - 1, GETDATE()) 
+0

您需要一个介于或大于小于的距离才能得到他所有的结果,而不仅仅是一天 – Matt

+0

此外,如果他的列中有时间组件 – Matt

0
SELECT 
    DATEFROMPARTS(YEAR(DATEADD(month,-1,GETDATE())),MONTH(DATEADD(month,-1,GETDATE())),1) AS StartOfLastMonth 
    ,DATEADD(day,-1,(DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()),1))) AS EndOfLastMonthAsDate 
    ,DATEADD(day,-3,CAST(DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()),1) AS DATETIME)) AS EndOfLastMonthMidngith 
    ,CAST(DATEADD(month,-1,GETDATE()) AS DATE) AS OneMonthAgoStrartOfDay 
    ,CAST(GETDATE() AS DATE) AS StartOfToday 
    ,DATEADD(MS,-3,CAST(CAST(GETDATE() AS DATE) AS DATETIME)) AS MidnightLastNight 

没关系,人们肯定说明有很多不同的答案,你的问题并都在类似的前提下建造的。使用DATEADD()与一个负数回去一个月。或者比较月份和年份,看看它们是否相同。前者是在1个月前到今天,后者是在上个月。

所有的答案到目前为止,预计@DasBlinkenLight和@TimBiegeleisen,失败,如果你有一个要考虑到你列的TIME组件和GETDATE()功能。如果您的专栏是DATETIME,您需要考虑这一点。以上SELECT查询,将通过一些方法来达到我怀疑将满足您的需求的不同日期。

至于使用BETWEEN日期要小心!因为你输入的数值是包含性的,所以如果你将GETDATE()置于中间语句的右边,你也会得到今天的结果,但是你可能真的想要达到今天,在这种情况下你应该改变你的右边参数。另外我不确定Oracle,mysql等,但Micrsofot SQL-Server精确到.003毫秒。所以如果你真的想看一个日期的午夜,你应该看看23:59:59.997,因为.998和.999会在第二天结束。

同样为了进一步简化,如果你不想要时间组件,你也可以把你的专栏投到DATE,并且它基本上没有时间和BETWEEN,因为有一点更清晰,例如, CAST(n.JOIN_DATE AS DATE)

在这个问题上肯定还有其他的问题,我鼓励你研究。

-1

我知道这是一个简单的,我错过了一些东西。我的代码是错误的,因为我收到了很多回应,并且我正在比较苹果和橙子,而不是苹果。一旦我在dateadd函数周围添加了Month(),它就起作用了。

+0

请注意您的数据何时包含多年。如果你想要上个月的所有时间,你需要比较上个月的YEAR和你的n.JOIN_DATE和这个月的YEAR。否则,如果你的数据有多年,你会在结果中的每一年获得该月的数据 – Matt