在两个日期之间获取每月的开始和结束时间

时间:2013-08-16 21:48:45

标签: sql sql-server sql-server-2008 tsql

我有这张桌子:

create table #tbl
 (
    dt datetime
 )

 insert into #tbl values ('2013-01-01 00:00:00')
 insert into #tbl values ('2013-02-01 00:00:00')
 insert into #tbl values ('2013-02-02 00:00:00')
 insert into #tbl values ('2013-03-01 00:00:00')

我需要得到每个不同月份的开始和结束,换句话说,这是预期的结果:

[start]                    [end]
 2013-01-01 00:00:00.000    2013-01-31 23:59:59.997
 2013-02-01 00:00:00.000    2013-02-28 23:59:59.997
 2013-03-01 00:00:00.000    2013-03-31 23:59:59.997

我不知道该怎么做。 Plz帮助。

select
 dateadd(mm, datediff(mm, 0, ???, 0),
 dateadd(ms, -3, dateadd(mm, datediff(m, 0, ??? + 1, 0))

我正在使用MS SQL Server 2008。

3 个答案:

答案 0 :(得分:1)

试试这个:

SELECT DISTINCT DATEADD(month, DATEDIFF(month, 0, MyDate), 0) as startOfMonth,
                DATEADD(day, -1, DATEADD(month, 1, DATEADD(day, 1 - day(MyDate), MyDate))) as endOfMonth
FROM MyTable

答案 1 :(得分:1)

;with dm as (
    select distinct rm = datediff(mm, 0, dt)
    from #tbl t
)
select ms.[start], me.[end]
from dm
    cross apply (select dateadd(mm, dm.rm, 0)) ms([start])
    cross apply (select dateadd(ms, -3, dateadd(month, 1, ms.Value))) me([end])

逻辑如下。对于表格中的每个日期,查找自{date} rm起的0天数(即自1900年1月以来,cast(0 as datetime)为1900年1月1日)。为避免重复使用distinct

select distinct rm = datediff(mm, 0, dt)
from #tbl t

上述语句包含在名为dm的CTE中。然后,对于dm中的每一行,使用表达式dateadd(mm, dm.rm, 0)计算相应月份开始的日期(添加自1900年1月以来经过的月数,即使原始日期位于中间)。它被添加到使用cross apply构造进行查询,因为它的值不仅会用于select,还会用于计算月末日期。结束日期的计算方法是,将一个月添加到开始日期并减去3毫秒(以便结束日期不是下个月开始的日期)。

答案 2 :(得分:0)

对于结束日期,您可以在该月的第一天添加1个月,然后减去3毫秒。

SELECT 
    [end] = DATEADD(ms,-3, DATEADD(MM,1,DATEADD(MM,DATEDIFF(MM,0,dt),0)))