如何获得所选月份之间的第一个日期和最后日期?
例如我输入2015年和09年至2016年08月
返回值必须为:
StartDate EndDate
20150901 20150930
20151001 20151031
20151101 20151130
20151201 20151231
20160101 20160131
20160201 20160229
20160301 20160331
20160401 20160430
20160501 20160531
20160601 20160630
20160701 20160731
20160801 20160831
我发现多个查询执行相同但只插入1个日期。例如:
DECLARE @mydate DATETIME
SELECT @mydate = GETDATE()
SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(@mydate)-1),@mydate),101) AS Date_Value,
'First Day of Current Month' AS Date_Type
UNION
SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,@mydate))),DATEADD(mm,1,@mydate)),101) ,
'Last Day of Current Month'
但我无法找到一个可以为Between语句
执行此操作的人答案 0 :(得分:1)
我有两个udf可以单独使用或联合使用。它们使用可变的dateparts和/或增量动态创建日期范围。
Select * from [dbo].[udf-Create-Range-Date-Span]('2015-09-01','2016-08-01','MM',1)
DateR1 DateR2
2015-09-01 00:00:00.000 2015-10-01 00:00:00.000
2015-10-01 00:00:00.000 2015-11-01 00:00:00.000
2015-11-01 00:00:00.000 2015-12-01 00:00:00.000
2015-12-01 00:00:00.000 2016-01-01 00:00:00.000
2016-01-01 00:00:00.000 2016-02-01 00:00:00.000
2016-02-01 00:00:00.000 2016-03-01 00:00:00.000
2016-03-01 00:00:00.000 2016-04-01 00:00:00.000
2016-04-01 00:00:00.000 2016-05-01 00:00:00.000
2016-05-01 00:00:00.000 2016-06-01 00:00:00.000
2016-06-01 00:00:00.000 2016-07-01 00:00:00.000
2016-07-01 00:00:00.000 2016-08-01 00:00:00.000
现在,我专门使用上限,这样我就可以查询DateR1和DateR2之间的数据(包括时间)和
但是,稍微扭曲一下,就可以改变输出。例如:
Select DateR1=cast(DateR1 as Date),DateR2=DateAdd(DD,-1,cast(DateR2 as Date)) from [dbo].[udf-Create-Range-Date-Span]('2015-09-01','2016-08-01','MM',1)
DateR1 DateR2
2015-09-01 2015-09-30
2015-10-01 2015-10-31
2015-11-01 2015-11-30
2015-12-01 2015-12-31
2016-01-01 2016-01-31
2016-02-01 2016-02-29
2016-03-01 2016-03-31
2016-04-01 2016-04-30
2016-05-01 2016-05-31
2016-06-01 2016-06-30
2016-07-01 2016-07-31
这两个功能如下:
CREATE FUNCTION [dbo].[udf-Create-Range-Date] (@DateFrom datetime,@DateTo datetime,@DatePart varchar(10),@Incr int)
Returns
@ReturnVal Table (RetVal datetime)
As
Begin
With DateTable As (
Select DateFrom = @DateFrom
Union All
Select Case @DatePart
When 'YY' then DateAdd(YY, @Incr, df.dateFrom)
When 'QQ' then DateAdd(QQ, @Incr, df.dateFrom)
When 'MM' then DateAdd(MM, @Incr, df.dateFrom)
When 'WK' then DateAdd(WK, @Incr, df.dateFrom)
When 'DD' then DateAdd(DD, @Incr, df.dateFrom)
When 'HH' then DateAdd(HH, @Incr, df.dateFrom)
When 'MI' then DateAdd(MI, @Incr, df.dateFrom)
When 'SS' then DateAdd(SS, @Incr, df.dateFrom)
End
From DateTable DF
Where DF.DateFrom < @DateTo
)
Insert into @ReturnVal(RetVal) Select DateFrom From DateTable option (maxrecursion 32767)
Return
End
和
CREATE FUNCTION [dbo].[udf-Create-Range-Date-Span] (@Date1 datetime,@Date2 datetime,@DatePart varchar(10),@Incr int)
-- Syntax Select * from [dbo].[udf-Create-Range-Date-Span]('2016-10-01','2020-10-01','YY',1)
-- Syntax Select * from [dbo].[udf-Create-Range-Date-Span]('2016-01-01','2016-12-31','MM',1)
-- Syntax Select * from [dbo].[udf-Create-Range-Date-Span]('2016-10-01','2016-10-31','MI',15)
-- Syntax Select * from [dbo].[udf-Create-Range-Date-Span]('2016-10-01','2016-10-02','SS',1)
Returns Table
As
Return (
Select DateR1 = RetVal
,DateR2 = LEAD(RetVal,1,@Date2) OVER (ORDER BY RetVal)
From (Select * from [dbo].[udf-Create-Range-Date](@Date1,@Date2,@DatePart,@Incr) ) A
Where RetVal<@Date2
)
答案 1 :(得分:1)
您不需要UDF
- 您可以使用单个查询执行此操作:
Declare @FromYear Int = 2015,
@FromMonth Int = 9,
@ToYear Int = 2016,
@ToMonth Int = 8
Declare @FromDate Date = (Select DateAdd(Year, @FromYear - 1900, DateAdd(Month, @FromMonth - 1, 0))),
@ToDate Date = (Select DateAdd(Year, @ToYear - 1900, DateAdd(Month, @ToMonth - 1, 0)))
;With Date (Date) As
(
Select @FromDate Union All
Select DateAdd(Month, 1, Date)
From Date
Where Date < @ToDate
)
Select Convert(Varchar, Year(Date)) + Right('00' + Convert(Varchar, Month(Date)), 2) + Right('00' + Convert(Varchar, Day(Date)), 2) As StartDate,
Convert(Varchar, Year(Date)) + Right('00' + Convert(Varchar, Month(Date)), 2) + Right('00' + Convert(Varchar, Day(DateAdd(Day, -1, DateAdd(Month, DateDiff(Month, 0, Date) + 1, 0)))), 2) As EndDate
From Date
Option (MaxRecursion 0)
输出
StartDate EndDate
20150901 20150930
20151001 20151031
20151101 20151130
20151201 20151231
20160101 20160131
20160201 20160229
20160301 20160331
20160401 20160430
20160501 20160531
20160601 20160630
20160701 20160731
20160801 20160831
但是,如果您能够迁移到SQL Server 2012或更高版本,则查询会更简单:
Declare @FromYear Int = 2015,
@FromMonth Int = 9,
@ToYear Int = 2016,
@ToMonth Int = 8
Declare @FromDate Date = DateFromParts(@FromYear, @FromMonth, 1),
@ToDate Date = DateFromParts(@ToYear, @ToMonth, 1)
;With Date (Date) As
(
Select @FromDate Union All
Select DateAdd(Month, 1, Date)
From Date
Where Date < @ToDate
)
Select Format(Date, N'yyyyMMdd') As StartDate,
Format(EoMonth(Date), N'yyyyMMdd') As EndDate
From Date
Option (MaxRecursion 0)
答案 2 :(得分:0)
试试这个。它也是一个非常小的脚本。我喜欢Siyual的CTE概念。但这要短得多。
DECLARE @inputYear INT = 2015,
@inputMonth INT = 09
SELECT DATEADD(MONTH, @inputMonth-1, DATEADD(YEAR, @inputYear-1900, 0)) AS FirstDayOfTheMonth,
DATEADD(s,-1, DATEADD(MONTH, @inputMonth, DATEADD(YEAR, @inputYear-1900, 0))) AS LastDayOfTheMonth
答案 3 :(得分:-1)
使用一个ANSI sql语句也可以完成任务。 但是,您需要两个表ALL_YEARS和ALL_MONTHS,其中包含已使用的年和月集。
E.g。如果考虑1900年到2099年之间的可能年份,表ALL_YEARS必须包含1900年到2099年之间的数字。 表ALL_MONTHS必须包含1到12之间的数字。
使用这两个表,该语句如下所示:
select to_date('01.' || to_char(all_months.month_value) || '.' || to_char(all_years.year_value ), 'dd.mm.yyyy') first_day ,
add_months(to_date('01.' || to_char(all_months.month_value) || '.' || to_char(all_years.year_value ), 'dd.mm.yyyy'), 1) -1 last_day
from all_years,
all_months
where to_date('01.' || to_char(all_months.month_value) || '.' || to_char(all_years.year_value ), 'dd.mm.yyyy') between
to_date('01.02.2014', 'dd.mm.yyyy') and
to_date('01.07.2016', 'dd.mm.yyyy');
输出如下:
01.02.14 28.02.14
01.03.14 31.03.14
01.04.14 30.04.14
01.05.14 31.05.14
01.06.14 30.06.14
...
01.06.16 30.06.16
01.07.16 31.07.16