在SQL Server中获取最近的句点日期

时间:2017-05-03 07:18:04

标签: sql-server

假设我每个月有3个时期。

那是

6th day - 15th day 16th day - 25th day 26th day - 5th day (next month)

我想将当前日期四舍五入到最接近的结束时间。

结果应该是这样的:

My Date     |  Result Date
2017-06-03  |  2017-05-25
2017-06-08  |  2017-06-05
2017-06-15  |  2017-06-05
2017-06-21  |  2017-06-15
2017-06-24  |  2017-06-15
2017-06-25  |  2017-06-15
2017-06-26  |  2017-06-25
2017-06-28  |  2017-06-25
2017-07-01  |  2017-06-25

如何在SQL Server中执行此操作?

我更新了我的要求。我想找到另一种方法,而不是使用CASE ... WHEN ...子句。我已经用这种方式解决了这个问题。 :)

我只是想知道是否有另一种解决方法。感谢

3 个答案:

答案 0 :(得分:1)

你可以使用CASE ... WHEN ...DateFromParts(在SQL 2012+中可用)这样

DECLARE @SampleData AS TABLE (DateValue date)

INSERT INTO @SampleData VALUES 
('2017-06-03'),('2017-06-08'),('2017-06-15'),('2017-06-21'),
('2017-06-24'),('2017-06-25'),('2017-06-26'),('2017-06-28'),
('2017-07-01' )


SELECT sd.DateValue AS [My date],
      CASE 
         WHEN datepart(day,sd.DateValue) BETWEEN 6 AND 15 
                THEN DateFromParts(year(sd.DateValue), month(sd.DateValue), 5)
         WHEN datepart(day,sd.DateValue) BETWEEN 16 AND 25
                THEN DateFromParts(year(sd.DateValue), month(sd.DateValue), 15)
         ELSE DateFromParts(year(dateadd(day, - 6, sd.DateValue)), month(dateadd(day, - 6, sd.DateValue)), 25)
      END as [Result Date]
FROM @SampleData sd

注意:如果您的日期在26th day - 5th day,那么dateadd(day, - 6, sd.DateValue)会准确返回上一期的年份和月份。

演示链接:http://rextester.com/LTTWC54961

答案 1 :(得分:0)

你可以试试这个:

Declare @t table (datevalue date)

insert into @t values ('2017-06-03'),('2017-06-08'),('2017-06-15'),('2017-06-21'),('2017-06-24'),('2017-06-25'),('2017-06-26'),('2017-06-28'),('2017-07-01' )
--2017-06-03  |  2017-05-25
--2017-06-08  |  2017-06-05
--2017-06-15  |  2017-06-05
--2017-06-21  |  2017-06-15
--2017-06-24  |  2017-06-15
--2017-06-25  |  2017-06-15
--2017-06-26  |  2017-06-25
--2017-06-28  |  2017-06-25
--2017-07-01  |  2017-06-25

Select datevalue, cast ( cast( year(datevalue) as varchar(10)) +'/' + cast( month(datevalue) as varchar(10)) + '/26' as date) olddate,
cast ( cast( year(datevalue) as varchar(10)) +'/' + cast( month(datevalue)+1 as varchar(10)) + '/5' as date) newdate,
case 
    when day(datevalue) between 6 and 15 then '5-' + cast( month(datevalue) as varchar(10)) + '-' + cast( year(datevalue) as varchar(10)) 
    when day(datevalue) between 16 and 25 then '15-' + cast( month(datevalue) as varchar(10)) + '-' + cast( year(datevalue) as varchar(10)) 
    when datevalue between cast ( cast( year(datevalue)-1 as varchar(10)) +'/' + cast( month(datevalue) as varchar(10)) + '/26' as date) and cast ( cast( year(datevalue) as varchar(10)) +'/' + cast( month(datevalue) as varchar(10)) + '/5' as date)
    then '25-' + cast( month(datevalue)-1 as varchar(10)) + '-' + cast( year(datevalue) as varchar(10)) 
    else  '25-' + cast( month(datevalue) as varchar(10)) + '-' + cast( year(datevalue) as varchar(10)) 
end
from @t

答案 2 :(得分:0)

这似乎可以解决问题:

declare @t table (MyDate date,Expected date)
insert into @t(MyDate,Expected) values
('20170603','20170525'),
('20170608','20170605'),
('20170615','20170605'),
('20170621','20170615'),
('20170624','20170615'),
('20170625','20170615'),
('20170626','20170625'),
('20170628','20170625'),
('20170701','20170625')

select
    t.*,
    CASE
        WHEN Day25 < MyDate THEN Day25
        WHEN Day15 < MyDate THEN Day15
        WHEN Day05 < MyDate THEN Day05
        ELSE
            DATEADD(month,DATEDIFF(month,'20010101',MyDate),'20001225')
    END as Actual,
    u.*
from
    @t t
        cross apply
    (
        select
            DATEADD(month,DATEDIFF(month,'20010101',t.MyDate),'20010105') as Day05,
            DATEADD(month,DATEDIFF(month,'20010101',t.MyDate),'20010115') as Day15,
            DATEADD(month,DATEDIFF(month,'20010101',t.MyDate),'20010125') as Day25
    ) u

基本上,对于每个日期,我们在同一个月内计算可能的截止日期,然后选择在“我的”日期之前的最新截止日期。

如果这些都不适用,那么我们计算上个月的第25个

结果:

MyDate     Expected   Actual                  Day05                   Day15                   Day25
---------- ---------- ----------------------- ----------------------- ----------------------- -----------------------
2017-06-03 2017-05-25 2017-05-25 00:00:00.000 2017-06-05 00:00:00.000 2017-06-15 00:00:00.000 2017-06-25 00:00:00.000
2017-06-08 2017-06-05 2017-06-05 00:00:00.000 2017-06-05 00:00:00.000 2017-06-15 00:00:00.000 2017-06-25 00:00:00.000
2017-06-15 2017-06-05 2017-06-05 00:00:00.000 2017-06-05 00:00:00.000 2017-06-15 00:00:00.000 2017-06-25 00:00:00.000
2017-06-21 2017-06-15 2017-06-15 00:00:00.000 2017-06-05 00:00:00.000 2017-06-15 00:00:00.000 2017-06-25 00:00:00.000
2017-06-24 2017-06-15 2017-06-15 00:00:00.000 2017-06-05 00:00:00.000 2017-06-15 00:00:00.000 2017-06-25 00:00:00.000
2017-06-25 2017-06-15 2017-06-15 00:00:00.000 2017-06-05 00:00:00.000 2017-06-15 00:00:00.000 2017-06-25 00:00:00.000
2017-06-26 2017-06-25 2017-06-25 00:00:00.000 2017-06-05 00:00:00.000 2017-06-15 00:00:00.000 2017-06-25 00:00:00.000
2017-06-28 2017-06-25 2017-06-25 00:00:00.000 2017-06-05 00:00:00.000 2017-06-15 00:00:00.000 2017-06-25 00:00:00.000
2017-07-01 2017-06-25 2017-06-25 00:00:00.000 2017-07-05 00:00:00.000 2017-07-15 00:00:00.000 2017-07-25 00:00:00.000

(我刚刚在此结果中包含了u列,因此您可以看到它们是如何制定出来的)

DATEADD / DATEDIFF表达式中使用的常量日期有些随意 - 它们只是被选中,以便它们之间具有特定的关系,以便我们希望将相同的关系应用于{ {1}}。

如果MyDate是带有时间组件的MyDatedatetime,那么您可能还想将其强制转换为datetime2或以其他方式删除时间组件,然后再使用它在比较中,取决于您的确切要求。