在 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 中创建以日期为范围分区的表

如何根据行创建日期在 PostgreSQL 中创建自定义序列?

如何在 Flutter 中创建自定义下拉列表?

在片段中创建自定义列表视图时出错。必需的活动,找到的片段

如何在 GraphQL 中创建自定义对象列表

如何在 Blend 中创建自定义列表