2

我有这张桌子:

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

我不知道该怎么做。请帮忙。

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

我正在使用 MS SQL Server 2008。

4

3 回答 3

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
于 2013-08-16T21:54:02.220 回答
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])

逻辑如下。对于表中的每个日期,找出rm自日期以来经过的月数0(即自 1900 年 1 月以来,如 1900 年cast(0 as datetime)1 月 1 日)。为避免重复distinct使用:

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

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

于 2013-08-16T22:05:59.390 回答
0

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

SELECT 
    [end] = DATEADD(ms,-3, DATEADD(MM,1,DATEADD(MM,DATEDIFF(MM,0,dt),0)))
于 2013-08-16T22:00:55.820 回答