在 SQL Server 中创建自定义日期范围列表以便于使用
Posted
技术标签:
【中文标题】在 SQL Server 中创建自定义日期范围列表以便于使用【英文标题】:Creating a list of custom Date Ranges for ease of use, in SQL Server 【发布时间】:2020-10-08 16:01:49 【问题描述】:给定一个日期(例如今天的日期,“2020 年 10 月 8 日”)和日期范围列表(昨天、明天、上周、下周、上个月、下个月等),我们如何到达在必要的日期范围内,通过 SQL。
Yesterday 2020-10-07 00:00:00.000 2020-10-07 23:59:59.000
Tomorrow 2020-10-09 00:00:00.000 2020-10-09 23:59:59.000
Last Week 2020-09-27 00:00:00.000 2020-10-03 23:59:59.000
Next Week 2020-10-11 00:00:00.000 2020-10-17 23:59:59.000
Last Month 2020-09-01 00:00:00.000 2020-09-30 23:59:59.000
Next Month 2020-11-01 00:00:00.000 2020-11-30 23:59:59.000
【问题讨论】:
日期函数是高度特定于供应商的。请用您正在运行的数据库标记您的问题:mysql、oracle、sqlserver...? 明确标题,添加更具体的标签。 为什么你认为23:59:59
是一天的结束?这有可能在任何一个方向上咬你(丢失数据或四舍五入并包含太多数据)。尝试将范围视为“大于等于范围的开始,小于下一个范围的开始”。找到下个月的月初比找到本月的月底要容易得多。
另见 mssqltips.com/sqlservertip/6088/… 和 sqlblog.org/2011/10/19/… 和 sqlblog.org/2019/09/12/… 和 mssqltips.com/sqlservertip/6072/… ...虽然整个问答更像是一篇博文,而不是问答。
@AaronBertrand 这正是一篇博文。他们回答了自己的问题
【参考方案1】:
作为起点,我们有一个 Dates 表:
CREATE TABLE [dbo].[sysDate](
[DateKey] [int] NOT NULL,
[Date] [datetime] NOT NULL,
[Day] [char](10) NULL,
[DayOfWeek] [smallint] NULL,
[DayOfMonth] [smallint] NULL,
[DayOfYear] [smallint] NULL,
[PreviousDay] [datetime] NULL,
[NextDay] [datetime] NULL,
[WeekOfYear] [smallint] NULL,
[Month] [char](10) NULL,
[MonthOfYear] [smallint] NULL,
[QuarterOfYear] [smallint] NULL,
[Year] [int] NULL,
[FiscalYearString] [varchar](9) NULL,
[FiscalQuarter] [int] NULL,
[FiscalQuarterStartDate] [datetime] NULL,
[FiscalQuarterEndDate] [datetime] NULL,
[FiscalYear] [int] NULL,
[FiscalYearStartDate] [datetime] NULL,
[FiscalYearEndDate] [datetime] NULL
) ON [PRIMARY]
这是我们多年前创建的,其中填充了 1900 年至 2030 年的数据,它还具有识别会计期间的额外好处。大多数企业使用从 4 月 1 日开始的会计年度,但情况并非总是如此。
为了应对这一挑战,我们决定希望能够根据需要灵活地添加新范围,而无需额外自定义生成范围的存储过程。然后,我们需要一个表格来保存将日期转换为其范围的“recipie”。
CREATE TABLE [dbo].[CustomDateRanges](
[DateRangeID] [int] IDENTITY(1,1) NOT NULL,
[DateRangeLabel] [varchar](50) NOT NULL,
[DisplayOrder] [int] NULL,
[isPast] [bit] NULL,
[isPresent] [bit] NULL,
[isFuture] [bit] NULL,
[StartDateAdjuster] [varchar](5) NULL,
[StartDayOfWeekAdjuster] [varchar](5) NULL,
[StartDayOfMonthAdjuster] [varchar](5) NULL,
[StartDayOfYearAdjuster] [varchar](5) NULL,
[StartWeekOfYearAdjuster] [varchar](5) NULL,
[StartMonthOfYearAdjuster] [varchar](5) NULL,
[StartQuarterOfYearAdjuster] [varchar](5) NULL,
[StartYearAdjuster] [varchar](5) NULL,
[StartFiscalYearAdjuster] [varchar](5) NULL,
[StartFiscalQuarterAdjuster] [varchar](5) NULL,
[EndDateAdjuster] [varchar](5) NULL,
[EndDayOfWeekAdjuster] [varchar](5) NULL,
[EndDayOfMonthAdjuster] [varchar](5) NULL,
[EndDayOfYearAdjuster] [varchar](5) NULL,
[EndWeekOfYearAdjuster] [varchar](5) NULL,
[EndMonthOfYearAdjuster] [varchar](5) NULL,
[EndQuarterOfYearAdjuster] [varchar](5) NULL,
[EndYearAdjuster] [varchar](5) NULL,
[EndFiscalYearAdjuster] [varchar](5) NULL,
[EndFiscalQuarterAdjuster] [varchar](5) NULL
)
为了识别一个范围,我们现在声明需要进行哪些操作才能将给定日期取为其范围的开头,然后将同一日期取为其范围的结尾。 CustomDateRanges
表中的 NULL 列表示相关字段不需要任何操作。调整器列中的允许值为:
+<number> -- used to add <number> to the element
-<number> -- used to subtract <number> from the element
<number> -- used to explicitly set the element to <number>
'END' -- used to set the element to its last valid value, but only for "End" adjusters
我们将数据添加到CustomDateRanges
INSERT INTO CustomDateRanges(DateRangeLabel, DisplayOrder, isPast, isPresent, isFuture, StartDateAdjuster, StartDayOfWeekAdjuster, StartDayOfMonthAdjuster, StartDayOfYearAdjuster, StartWeekOfYearAdjuster, StartMonthOfYearAdjuster, StartQuarterOfYearAdjuster, StartYearAdjuster, StartFiscalYearAdjuster, StartFiscalQuarterAdjuster, EndDateAdjuster, EndDayOfWeekAdjuster, EndDayOfMonthAdjuster, EndDayOfYearAdjuster, EndWeekOfYearAdjuster, EndMonthOfYearAdjuster, EndQuarterOfYearAdjuster, EndYearAdjuster, EndFiscalYearAdjuster, EndFiscalQuarterAdjuster)
VALUES
-- DateRangeLabel StartDateAdjuster StartMonthOfYearAdjuster EndDateAdjuster EndMonthOfYearAdjuster
-- | |DisplayOrder| StartDayOfWeekAdjuster | StartQuarterOfYearAdjuster | EndDayOfWeekAdjuster | EndQuarterOfYearAdjuster
-- | | isPast | | StartDayOfMonthAdjuster | StartYearAdjuster | | EndDayOfMonthAdjuster| | EndYearAdjuster
-- | | | isPresent | | StartDayOfYearAdjuster | StartFiscalYearAdjuster | EndDayOfYearAdjuster | | EndFiscalYearAdjuster
-- | | | | isFuture | | | StartWeekOfYearAdjuster | StartFiscalQuarterAdjuster | EndWeekOfYearAdjuster| | EndFiscalQuarterAdjuster
-- | | | | | | | | | | | | | | | | | | | | | | | | |
('Yesterday', NULL, 1, 0, 0, '-1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
,('Today', NULL, 0, 1, 0, '+0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
,('Tomorrow', NULL, 0, 0, 1, '+1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
,('Last Week', NULL, 1, 0, 0, NULL, '1', NULL, NULL, '-1', NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
,('This Week', NULL, 0, 1, 0, NULL, '1', NULL, NULL, '+0', NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
,('Next Week', NULL, 0, 0, 1, NULL, '1', NULL, NULL, '+1', NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
,('Last Month', NULL, 1, 0, 0, NULL, NULL, '1', NULL, NULL, '-1', NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL, NULL, NULL, NULL, NULL)
,('This Month', NULL, 0, 1, 0, NULL, NULL, '1', NULL, NULL, '+0', NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL, NULL, NULL, NULL, NULL)
,('Next Month', NULL, 0, 0, 1, NULL, NULL, '1', NULL, NULL, '+1', NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL, NULL, NULL, NULL, NULL)
,('Last Quarter', NULL, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, '-1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL)
,('This Quarter', NULL, 0, 1, 0, NULL, NULL, NULL, NULL, NULL, NULL, '+0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL)
,('Next Quarter', NULL, 0, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, '+1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL, NULL)
,('Last Fiscal Quarter', NULL, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '-1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END')
,('This Fiscal Quarter', NULL, 0, 1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '+0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END')
,('Next Fiscal Quarter', NULL, 0, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '+1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END')
,('Last Year', NULL, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '-1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL)
,('This Year', NULL, 0, 1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '+0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL)
,('Next Year', NULL, 0, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '+1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL, NULL)
,('Last Fiscal Year', NULL, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '-1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL)
,('This Fiscal Year', NULL, 0, 1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '+0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL)
,('Next Fiscal Year', NULL, 0, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '+1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'END', NULL)
然后是执行操作的代码。代码中的第一步是去掉时间组件(通过CAST(CAST(@Date AS Date) AS DateTime)
,以确保对 sysDate 表的查找始终准确,代码中的最后一步是确保 StartDate 始终从午夜开始,并且EndDate 始终以23:59:59
结束,确保完整的日期范围。
CREATE PROCEDURE dbo.CalculateCustomDateRange(@Date DateTime, @DateRangeID int, @EndDateIsBeginningOfNextRange bit)
AS
BEGIN
/**************************************************************************************************************************************************
* Copyright: CCD Health Systems
* Written by: Daniel Bragg
* Creation Date: 06-Oct-2020
*
* Updates:
* Date Author Version Purpose
* 2020-Oct-08 Daniel Bragg 5.0.0 Added @EndDateIsBeginningOfNextRange, to permit us to use the output for both
* ([D] >= Start AND [D] <= End) -- @EndDateIsBeginningOfNextRange = 0
* and
* ([D] >= Start AND [D] < End) -- @EndDateIsBeginningOfNextRange = 1
*
*************************************************************************************************************************************************/
SET NOCOUNT ON
DECLARE @StartDate DateTime = CAST(CAST(@Date AS Date) AS DateTime)
DECLARE @EndDate DateTime = @StartDate
-- Values from CustomDateRanges table
DECLARE @DateRangeLabel varchar(50),
@DisplayOrder int,
@isPast bit,
@isPresent bit,
@isFuture bit,
@StartDateAdjuster varchar(5),
@StartDayOfWeekAdjuster varchar(5),
@StartDayOfMonthAdjuster varchar(5),
@StartDayOfYearAdjuster varchar(5),
@StartWeekOfYearAdjuster varchar(5),
@StartMonthOfYearAdjuster varchar(5),
@StartQuarterOfYearAdjuster varchar(5),
@StartYearAdjuster varchar(5),
@StartFiscalYearAdjuster varchar(5),
@StartFiscalQuarterAdjuster varchar(5),
@EndDateAdjuster varchar(5),
@EndDayOfWeekAdjuster varchar(5),
@EndDayOfMonthAdjuster varchar(5),
@EndDayOfYearAdjuster varchar(5),
@EndWeekOfYearAdjuster varchar(5),
@EndMonthOfYearAdjuster varchar(5),
@EndQuarterOfYearAdjuster varchar(5),
@EndYearAdjuster varchar(5),
@EndFiscalYearAdjuster varchar(5),
@EndFiscalQuarterAdjuster varchar(5)
SELECT @DateRangeLabel=DateRangeLabel, @DisplayOrder=DisplayOrder, @isPast=isPast, @isPresent=isPresent, @isFuture=isFuture
, @StartDateAdjuster=StartDateAdjuster, @StartDayOfWeekAdjuster=StartDayOfWeekAdjuster, @StartDayOfMonthAdjuster=StartDayOfMonthAdjuster
, @StartDayOfYearAdjuster=StartDayOfYearAdjuster, @StartWeekOfYearAdjuster=StartWeekOfYearAdjuster, @StartMonthOfYearAdjuster=StartMonthOfYearAdjuster
, @StartQuarterOfYearAdjuster=StartQuarterOfYearAdjuster, @StartYearAdjuster=StartYearAdjuster, @StartFiscalYearAdjuster=StartFiscalYearAdjuster
, @StartFiscalQuarterAdjuster=StartFiscalQuarterAdjuster, @EndDateAdjuster=EndDateAdjuster, @EndDayOfWeekAdjuster=EndDayOfWeekAdjuster
, @EndDayOfMonthAdjuster=EndDayOfMonthAdjuster, @EndDayOfYearAdjuster=EndDayOfYearAdjuster, @EndWeekOfYearAdjuster=EndWeekOfYearAdjuster
, @EndMonthOfYearAdjuster=EndMonthOfYearAdjuster, @EndQuarterOfYearAdjuster=EndQuarterOfYearAdjuster, @EndYearAdjuster=EndYearAdjuster
, @EndFiscalYearAdjuster=EndFiscalYearAdjuster, @EndFiscalQuarterAdjuster=EndFiscalQuarterAdjuster
FROM CustomDateRanges WHERE DateRangeID = @DateRangeID
DECLARE @DayOfWeek smallint,
@DayOfMonth smallint,
@DayOfYear smallint,
@PreviousDay datetime,
@NextDay datetime,
@WeekOfYear smallint,
@MonthOfYear smallint,
@QuarterOfYear smallint,
@Year int,
@FiscalYear int,
@FiscalQuarter int
DECLARE @AdjustFullYears int
DECLARE @AdjustRemainingQuarters int
DECLARE @Value int
--------------------------------
-- Perform Start Calculations --
--------------------------------
-- Set Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
IF (@StartFiscalYearAdjuster IS NOT NULL) AND ISNUMERIC(@StartFiscalYearAdjuster) = 1
BEGIN
SET @Value = CAST(@StartFiscalYearAdjuster AS INT)
IF LEFT(@StartFiscalYearAdjuster,1) = '-' OR LEFT(@StartFiscalYearAdjuster,1) = '+' -- Adjust
SELECT @StartDate=MIN([Date]) FROM sysDate WHERE [FiscalYear]=@FiscalYear+@Value
ELSE
SELECT @StartDate=MIN([Date]) FROM sysDate WHERE [FiscalYear]=@Value
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
IF (@StartFiscalQuarterAdjuster IS NOT NULL) AND ISNUMERIC(@StartFiscalQuarterAdjuster) = 1
BEGIN
SET @Value = CAST(@StartFiscalQuarterAdjuster AS INT)
IF LEFT(@StartFiscalQuarterAdjuster,1) = '-' OR LEFT(@StartFiscalQuarterAdjuster,1) = '+' -- Adjust
BEGIN
-- Simplify
SET @FiscalQuarter=@FiscalQuarter+@Value
WHILE (@FiscalQuarter > 4)
BEGIN
SET @FiscalYear=@FiscalYear+1
SET @FiscalQuarter=@FiscalQuarter-4
END
WHILE (@FiscalQuarter < 1)
BEGIN
SET @FiscalYear=@FiscalYear-1
SET @FiscalQuarter=@FiscalQuarter+4
END
SELECT @StartDate=MIN(FiscalQuarterStartDate) FROM sysDate WHERE [FiscalYear]=@FiscalYear AND [FiscalQuarter]=@FiscalQuarter
END
ELSE
SELECT @StartDate=MIN(FiscalQuarterStartDate) FROM sysDate WHERE [FiscalYear]=@FiscalYear AND [FiscalQuarter]=@Value
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
IF (@StartYearAdjuster IS NOT NULL) AND ISNUMERIC(@StartYearAdjuster) = 1
BEGIN
SET @Value = CAST(@StartYearAdjuster AS INT)
IF LEFT(@StartYearAdjuster,1) = '-' OR LEFT(@StartYearAdjuster,1) = '+' -- Adjust
SET @StartDate = DATEFROMPARTS(@Year+@Value, 1, 1)
ELSE
SET @StartDate = DATEFROMPARTS(@Value, 1, 1)
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
IF (@StartQuarterOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@StartQuarterOfYearAdjuster) = 1
BEGIN
SET @Value = CAST(@StartQuarterOfYearAdjuster AS INT)
IF LEFT(@StartQuarterOfYearAdjuster,1) = '-' OR LEFT(@StartQuarterOfYearAdjuster,1) = '+' -- Adjust
BEGIN
SET @StartDate = DATEFROMPARTS(YEAR(@StartDate), 1, 1)
SET @StartDate = DATEADD(quarter, @QuarterOfYear+@Value-1, @StartDate)
END
ELSE
BEGIN
SET @StartDate = DATEFROMPARTS(YEAR(@StartDate), 1, 1)
SET @StartDate = DATEADD(quarter, @Value, @StartDate)
END
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
IF (@StartMonthOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@StartMonthOfYearAdjuster) = 1
BEGIN
SET @Value = CAST(@StartMonthOfYearAdjuster AS INT)
IF LEFT(@StartMonthOfYearAdjuster,1) = '-' OR LEFT(@StartMonthOfYearAdjuster,1) = '+' -- Adjust
SET @StartDate = DATEADD(month, @Value, @StartDate)
ELSE
SET @StartDate = DATEFROMPARTS(YEAR(@StartDate), @Value, DAY(@StartDate))
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
IF (@StartWeekOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@StartWeekOfYearAdjuster) = 1
BEGIN
SET @Value = CAST(@StartWeekOfYearAdjuster AS INT)
IF LEFT(@StartWeekOfYearAdjuster,1) = '-' OR LEFT(@StartWeekOfYearAdjuster,1) = '+' -- Adjust
SET @StartDate = DATEADD(week, @Value, @StartDate)
ELSE
SELECT TOP 1 @StartDate=[Date] FROM sysDate WHERE [Year]=@Year AND [WeekOfYear]=@Value ORDER BY [Year],[WeekOfYear],[Date]
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
IF (@StartDayOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@StartDayOfYearAdjuster) = 1
BEGIN
SET @Value = CAST(@StartDayOfYearAdjuster AS INT)
IF LEFT(@StartDayOfYearAdjuster,1) = '-' OR LEFT(@StartDayOfYearAdjuster,1) = '+' -- Adjust
SET @StartDate = DATEADD(day, @Value, @StartDate)
ELSE
BEGIN
SET @StartDate = DATEFROMPARTS(YEAR(@StartDate), 1, 1)
SET @StartDate = DATEADD(day, @Value, @StartDate)
END
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
IF (@StartDayOfMonthAdjuster IS NOT NULL) AND ISNUMERIC(@StartDayOfMonthAdjuster) = 1
BEGIN
SET @Value = CAST(@StartDayOfMonthAdjuster AS INT)
IF LEFT(@StartDayOfMonthAdjuster,1) = '-' OR LEFT(@StartDayOfMonthAdjuster,1) = '+' -- Adjust
SET @StartDate = DATEADD(day, @Value, @StartDate)
ELSE
SET @StartDate = DATEFROMPARTS(YEAR(@StartDate), MONTH(@StartDate), @Value)
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
IF (@StartDayOfWeekAdjuster IS NOT NULL) AND ISNUMERIC(@StartDayOfWeekAdjuster) = 1
BEGIN
SET @Value = CAST(@StartDayOfWeekAdjuster AS INT)
IF LEFT(@StartDayOfWeekAdjuster,1) = '-' OR LEFT(@StartDayOfWeekAdjuster,1) = '+' -- Adjust
SET @StartDate = DATEADD(week, @Value, @StartDate)
ELSE
SELECT @StartDate=[Date] FROM sysDate WHERE [Year]=@Year AND [WeekOfYear]=@WeekOfYear AND [DayOfWeek]=@Value
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
IF (@StartDateAdjuster IS NOT NULL) AND ISNUMERIC(@StartDateAdjuster) = 1
BEGIN
SET @Value = CAST(@StartDateAdjuster AS INT)
IF LEFT(@StartDateAdjuster,1) = '-' OR LEFT(@StartDateAdjuster,1) = '+' -- Adjust
SET @StartDate = DATEADD(day, @Value, @StartDate)
ELSE
SET @StartDate = DATEFROMPARTS(YEAR(@StartDate), MONTH(@StartDate), @Value)
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @StartDate
END
------------------------------
-- Perform End Calculations --
------------------------------
-- NOTE! End Date always starts from the Start Date as its calculation
SET @EndDate=@StartDate
-- Set Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @EndDate
IF (@EndFiscalYearAdjuster = 'END') OR ((@EndFiscalYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndFiscalYearAdjuster) = 1)
BEGIN
IF (@EndFiscalYearAdjuster = 'END')
SELECT @EndDate=MAX([DATE]) FROM sysDate WHERE [FiscalYear]=@FiscalYear
ELSE IF (@EndFiscalYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndFiscalYearAdjuster) = 1
BEGIN
SET @Value = CAST(@EndFiscalYearAdjuster AS INT)
IF LEFT(@EndFiscalYearAdjuster,1) = '-' OR LEFT(@EndFiscalYearAdjuster,1) = '+' -- Adjust
SELECT @EndDate=[Date] FROM sysDate WHERE [FiscalYear]=@FiscalYear+@Value AND [DayOfYear]=1
ELSE
SELECT @EndDate=[Date] FROM sysDate WHERE [FiscalYear]=@Value AND [DayOfYear]=1
END
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @EndDate
END
IF (@EndFiscalQuarterAdjuster = 'END') OR ((@EndFiscalQuarterAdjuster IS NOT NULL) AND ISNUMERIC(@EndFiscalQuarterAdjuster) = 1)
BEGIN
IF (@EndFiscalQuarterAdjuster = 'END')
SELECT @EndDate=MAX([DATE]) FROM sysDate WHERE [FiscalYear]=@FiscalYear AND [FiscalQuarter]=@FiscalQuarter
ELSE IF (@EndFiscalQuarterAdjuster IS NOT NULL) AND ISNUMERIC(@EndFiscalQuarterAdjuster) = 1
BEGIN
SET @Value = CAST(@EndFiscalQuarterAdjuster AS INT)
IF LEFT(@EndFiscalQuarterAdjuster,1) = '-' OR LEFT(@EndFiscalQuarterAdjuster,1) = '+' -- Adjust
BEGIN
SET @AdjustFullYears = @Value / 4
SET @AdjustRemainingQuarters = @Value % 4
-- Adjust to the beginning of the quarter, to not mess anything up.
SELECT @EndDate=FiscalQuarterEndDate FROM sysDate WHERE [Date]=@EndDate
SET @EndDate=DATEADD(year, @AdjustFullYears, @EndDate)
-- See if we need to adjust the year
IF (@QuarterOfYear + @AdjustRemainingQuarters) > 4
SELECT @EndDate=FiscalQuarterEndDate FROM sysDate WHERE [FiscalYear]=YEAR(@EndDate)+1 AND [FiscalQuarter]=(@FiscalQuarter + @AdjustRemainingQuarters - 4) AND [DayOfMonth]=@DayOfMonth
ELSE IF (@QuarterOfYear + @AdjustRemainingQuarters) < 1
SELECT @EndDate=FiscalQuarterEndDate FROM sysDate WHERE [FiscalYear]=YEAR(@EndDate)-1 AND [FiscalQuarter]=(@FiscalQuarter + @AdjustRemainingQuarters + 4) AND [DayOfMonth]=@DayOfMonth
ELSE
SELECT @EndDate=FiscalQuarterEndDate FROM sysDate WHERE [FiscalYear]=YEAR(@EndDate) AND [FiscalQuarter]=(@FiscalQuarter + @AdjustRemainingQuarters) AND [DayOfMonth]=@DayOfMonth
END
ELSE
SELECT @EndDate=FiscalQuarterEndDate FROM sysDate WHERE [FiscalYear]=YEAR(@EndDate) AND [FiscalQuarter]=@Value AND [DayOfMonth]=@DayOfMonth
END
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @EndDate
END
IF (@EndYearAdjuster = 'END') OR ((@EndYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndYearAdjuster) = 1)
BEGIN
IF (@EndYearAdjuster = 'END')
SELECT @EndDate=MAX([DATE]) FROM sysDate WHERE [Year]=@Year
ELSE IF (@EndYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndYearAdjuster) = 1
BEGIN
SET @Value = CAST(@EndYearAdjuster AS INT)
IF LEFT(@EndYearAdjuster,1) = '-' OR LEFT(@EndYearAdjuster,1) = '+' -- Adjust
SET @EndDate = DATEADD(year, @Value, @EndDate)
ELSE
SET @EndDate = DATEFROMPARTS(@Value, MONTH(@EndDate), DAY(@EndDate))
END
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @EndDate
END
IF (@EndQuarterOfYearAdjuster = 'END') OR ((@EndQuarterOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndQuarterOfYearAdjuster) = 1)
BEGIN
IF (@EndQuarterOfYearAdjuster = 'END')
SELECT @EndDate=MAX([DATE]) FROM sysDate WHERE [Year]=@Year AND [QuarterOfYear]=@QuarterOfYear
ELSE IF (@EndQuarterOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndQuarterOfYearAdjuster) = 1
BEGIN
SET @Value = CAST(@EndQuarterOfYearAdjuster AS INT)
IF LEFT(@EndQuarterOfYearAdjuster,1) = '-' OR LEFT(@EndQuarterOfYearAdjuster,1) = '+' -- Adjust
SET @EndDate = DATEADD(quarter, @Value, @EndDate)
ELSE
BEGIN
SET @EndDate = DATEFROMPARTS(YEAR(@EndDate), 1, 1)
SET @EndDate = DATEADD(quarter, @Value, @EndDate)
END
END
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @EndDate
END
IF (@EndMonthOfYearAdjuster = 'END') OR ((@EndMonthOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndMonthOfYearAdjuster) = 1)
BEGIN
IF (@EndMonthOfYearAdjuster = 'END')
SELECT @EndDate=MAX([DATE]) FROM sysDate WHERE [Year]=@Year AND [MonthOfYear]=@MonthOfYear
ELSE IF (@EndMonthOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndMonthOfYearAdjuster) = 1
BEGIN
SET @Value = CAST(@EndMonthOfYearAdjuster AS INT)
IF LEFT(@EndMonthOfYearAdjuster,1) = '-' OR LEFT(@EndMonthOfYearAdjuster,1) = '+' -- Adjust
SET @EndDate = DATEADD(month, @Value, @EndDate)
ELSE
SET @EndDate = DATEFROMPARTS(YEAR(@EndDate), @Value, DAY(@EndDate))
END
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @EndDate
END
IF (@EndWeekOfYearAdjuster = 'END') OR ((@EndWeekOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndWeekOfYearAdjuster) = 1)
BEGIN
IF (@EndWeekOfYearAdjuster = 'END')
SELECT @EndDate=MAX([DATE]) FROM sysDate WHERE [Year]=@Year AND [WeekOfYear]=@WeekOfYear
ELSE IF (@EndWeekOfYearAdjuster IS NOT NULL) AND ISNUMERIC(@EndWeekOfYearAdjuster) = 1
BEGIN
SET @Value = CAST(@EndWeekOfYearAdjuster AS INT)
IF LEFT(@EndWeekOfYearAdjuster,1) = '-' OR LEFT(@EndWeekOfYearAdjuster,1) = '+' -- Adjust
SET @EndDate = DATEADD(week, @Value, @EndDate)
ELSE
SELECT TOP 1 @EndDate=[Date] FROM sysDate WHERE [Year]=@Year AND [WeekOfYear]=@Value ORDER BY [Year],[WeekOfYear],[Date]
END
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @EndDate
END
-- Removed code for @EndDayOfYearAdjuster, @EndDayOfMonthAdjuster and @EndDayOfWeekAdjuster for brevity, but it's the same as the above code for the matching @Start blocks, but with the extra 'END' processing
IF (@EndDateAdjuster IS NOT NULL) AND ISNUMERIC(@EndDateAdjuster) = 1
BEGIN
-- Nothing is required, the End Date is already the Start Date
-- Update Date Specifics
SELECT @DayOfWeek=[DayOfWeek], @DayOfMonth=[DayOfMonth], @DayOfYear=[DayOfYear], @WeekOfYear=WeekOfYear, @MonthOfYear=[MonthOfYear], @QuarterOfYear=[QuarterOfYear], @Year=[Year], @FiscalYear=[FiscalYear], @FiscalQuarter=[FiscalQuarter] FROM sysDate WHERE [Date] = @EndDate
END
-- Return StartDate as the earliest point on that date
-- and EndDate as the lastest point on that date.
SELECT @Date AS [Date],
@DateRangeID AS [DateRangeID],
@DateRangeLabel AS [DateRangeLabel],
CAST(CAST(@StartDate AS Date) AS DateTime) AS [StartDate],
DATEADD(second, -1, DATEADD(day, 1, CAST(CAST(@EndDate AS Date) AS DateTime))) AS [EndDate]
END
【讨论】:
以上是关于在 SQL Server 中创建自定义日期范围列表以便于使用的主要内容,如果未能解决你的问题,请参考以下文章
在 SQL Server 2012 中创建以日期为范围分区的表