获取上个月的最后一个日期到最后一秒

时间:2015-12-31 05:03:47

标签: sql-server

我希望在执行查询时获得上个月的最后日期(无论是30还是31)和时间到最后一秒。 的 EG。 11/30/2015 11:59:59 PM

所以我有一个像

这样的查询
SELECT DATEADD(ss, (60*60*24)-1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), -1))

它解决了我的问题。但是,当我更改DATEDIFF部分并将0替换为1时,上面的查询与下面的查询之间有什么区别?

SELECT DATEADD(ss, (60*60*24)-1, DATEADD(MONTH, DATEDIFF(MONTH, 1, GETDATE()), -1))

这两个查询在运行时是否会提供相同的结果,或者我应该将其视为永久解决方案?

4 个答案:

答案 0 :(得分:2)

不要这样做;试图获得上个月最后一天的“最后一秒”

我在假设您尝试使用BETWEEN的情况下做出这个大胆的陈述,并且您关注的是这样的准确性:

select sum(value) from Atable
where [Adate] BETWEEN '20151201' AND '21051231 59:59:59'

但是,通过使用下个月的第一天,可以轻松解决在任何月份的最后一天到达最后一个时间点的复杂性。您还需要做的就是放弃使用BETWEEN。像这样:

select sum(value) from Atable
where [Adate] >= '20151201' and [Adate] < '21060101'

少于“本月的第一天”

这就是你解决难题的方法。

&安培;顺便说一下:smalldatetime,datetime和datetime2的精度(准确度)都有所不同,更不能使用BETWEEN。

http://sqlmag.com/t-sql/t-sql-best-practices-part-2

上查看“小心舍入错误。

具体来说,这样做:

DateLogged&lt; SELECT DATEADD(月,DATEDIFF(月,0,GETDATE()),0)

对于date,smalldatetime,datetime和datetime2列,这将是100%准确。

这是另一种尝试来解释为什么[the_next_day_at_00:00:00 + 0000000]是准确的并且使用22:59:59是不准确的。请注意样本数据的准确性

SQL Fiddle

MS SQL Server 2014架构设置

查询1

DECLARE @Tbl TABLE
    (  [ID] int identity(1,1)
     , [DT_a] datetime
     , [DT_b] datetime
     , [DT_c] datetime2
    )

INSERT INTO @Tbl
    ([Dt_a], [Dt_b], [Dt_c])
VALUES
    (
       '20151231 23:59:59'
     , '20151231 23:59:59.997'
     , '20151231 23:59:59.9999999'
    )

select
      'where [DT_b] <= 20151231 23:59:59' as FilterString
    , max([Dt_a])  as [Dt_a]
    , max([Dt_b])  as [Dt_b]
    , max([Dt_c])  as [Dt_c]
from @Tbl
where [DT_b] <= '20151231 23:59:59'

UNION ALL
select
      'where [DT_b] < 20160101'
    , max([Dt_a])  as [Dt_a]
    , max([Dt_b])  as [Dt_b]
    , max([Dt_c])  as [Dt_c]
from @Tbl
where [DT_b] < '20160101'

<强> Results

|                      FilterString |                       Dt_a |                       Dt_b |                        Dt_c |
|-----------------------------------|----------------------------|----------------------------|-----------------------------|
| where [DT_b] <= 20151231 23:59:59 |                     (null) |                     (null) |                      (null) |
|           where [DT_b] < 20160101 | December, 31 2015 23:59:59 | December, 31 2015 23:59:59 | 2015-12-31 23:59:59.9999999 |

数据准确性

为避免因时间单位舍入而导致的错误,请勿使用&lt; = 23:59:59

而是使用少于[the_next_day]

AND,因此避免在日期范围内使用BETWEEN。

答案 1 :(得分:0)

有关如何在SQL Server中使用或应该使用DATEDIFF的信息,请参阅此link。第二个参数,在你的情况下似乎没有区别的那个,应该是从结束日期(getdate())中减去的起始日期,以获得差异,然后转换为月份。我会尝试以典型的方式使用此功能并提供正确的开始日期。

以下是获得相同结果的另一种方法

SELECT DATEADD(ss, -1, '01/' + CONVERT(VARCHAR, DATEPART(MONTH, getdate())) + '/' + CONVERT(VARCHAR, DATEPART(YEAR, getdate())));

答案 2 :(得分:0)

这是因为DATEDIFF( MONTH, 0, GETDATE())功能

如果您使用整数作为第二个参数,则无论您在1900-01-01函数中使用的Interval如何,都会将其解释为datediff以来的天数。

例如:

   SELECT YEAR(0), MONTH(0), DAY(0); 
 year    month     day

 1900    1          1

现在,如果我在年,月,日递增0到1

SELECT YEAR(1), MONTH(1), DAY(1); 
 year    month     day

 1900    1          2

现在,如果我将值增加到365,

 SELECT YEAR(365), MONTH(365), DAY(365); 
 year      month     day

 1901    1          1

你可以看到年份增加了1。

有很多方法可以找出上个月的最后一个日期。这是我正在使用的那个。

SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))

答案 3 :(得分:0)

嗯,可以预期的是,如果将当前月份的第一天减去一毫秒,就会得到上个月的最后一个毫秒,但是如果使用datediff毫秒,-1仍然会得到第一个月的最后一个毫秒,这是行不通的您必须在月份的第几天执行datediff毫秒,-2才能达到997毫秒,而无法获得999或998。(不使用文本)。

select  dateadd(MILLISECOND,-2,dateadd(month, datediff(month, 0, getdate()), 0))

您会得到2020-01-31 23:59:59.997