【问题标题】:Convert WHERE clause to CASE expression将 WHERE 子句转换为 CASE 表达式
【发布时间】:2018-09-20 17:36:35
【问题描述】:

有人可以帮我用 CASE 重写这个(使用易于阅读的语法):

SELECT *
FROM TBL_A
WHERE COLUMN_A BETWEEN DATEADD(MONTH, DATEDIFF(MONTH, +1, GETDATE()), 0) 
                   AND DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()), -1)

【问题讨论】:

  • TABL_A 中有一个名为TABL_A 的列吗?这个查询应该做什么
  • 您根本没有有效的 SQL 查询。如果您没有查询,则无法将其重写为使用 CASE。
  • 刚刚更正了查询(添加了列名)。对不起,伙计们。
  • Column_A 在这两个日期之间时,想要返回什么? Case 表达式返回一个值。也许样本数据和您想要的结果会帮助我们更好地理解。
  • “易于阅读的语法”在这里也毫无意义。获得当前结果的唯一方法是使用凌乱的DateAdd(DateDiff(GetDate())) 逻辑。已经很简单了。

标签: sql-server case datediff dateadd getdate


【解决方案1】:

在 where 子句中使用 case expression 不会使其更易于阅读。您需要熟悉 T-SQL 中的日期处理,其中包括 dateadd()datediff() 函数。另外,getdate() 是一个系统函数,从服务器返回当前日期和时间。

先尝试运行这个:

select dateadd(day,0,0) [Zero Point of Zero Date in TSQL]

= 1900-01-01 00:00:00+00000

在 T-SQL 中,所有日期/时间都是从 1900 年 1 月 1 日开始计算的,因此 select 返回: 因为我们在零日期中添加了零天:dateadd(day,0,0)

现在您知道什么是零日期,将其与当前日期和时间进行比较可用于计算其他有用的日期,例如当月的第一天。试试这个:

SELECT DATEDIFF(MONTH, 0, GETDATE()) [Number of Months From Date Zero] 

= 1424

这将返回一个整数,该整数是自零以来的月数。在您的初始查询中,它使用 +1 而不是零,但它仍然返回相同的月数。

SELECT DATEDIFF(MONTH, +1, GETDATE()) [Number of Months From Date One] 

= 1424

现在,如果我们将 1424 个月添加到 1900-01-01(即“零日期”),我们会得到一个有趣的结果,即当月的第一天

select DATEADD(MONTH, DATEDIFF(MONTH, +1, GETDATE()), 0)  [1st Day of Current Month]

= 2018-09-01 00:00:00+00000

现在,运行以下是另一个有趣的日期:

select DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()), -1) [Last Day of Current Month]

= 2018-09-30 00:00:00+00000

所以,您的查询等同于:

SELECT *
FROM TBL_A
WHERE COLUMN_A BETWEEN "1st Day of Current Month"
                   AND "Last Day of Current Month"

我不能不说,我不喜欢您当前查询的工作方式,因为"Last Day of Current Month" 不是实际的月底,即 之后 24 小时2018-09-30 00:00:00+00000

有一种更好的方法可以准确定义所需的日期范围(在我看来):

select
  DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)   [Current Month Starts At]
, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())+1, 0) [Current Month Finishes At]

= 2018-09-01 00:00:00+00000 2018-10-01 00:00:00+00000 

我会将您的查询改写为:

SELECT *
FROM TBL_A
WHERE COLUMN_A >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)   -- "Current Month Starts At"
  AND COLUMN_A  < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())+1, 0) -- "Current Month Finishes At"

此方法将选择当前月份的所有数据,而不管COLUMN_A 中的时间精度如何(即数据类型:日期、小日期时间、日期时间或日期时间2)

上面列出的大多数查询都可以在这里运行:http://rextester.com/CTQ4148

【讨论】:

    【解决方案2】:

    创建日期维度可以真正简化这样的事情;特别是如果您想为财政月或其他任何内容添加列。从表中提取日期标签或值,将它们分配给变量,并在查询中使用它们。更容易和更清洁。出错的空间也更小。很确定这个查询是可靠的,但是如果你决定使用它,你应该审核一些记录。

    这是桌子:

    CREATE TABLE dbo.Dates (
        DateId DATE NOT NULL CONSTRAINT PK_Dates PRIMARY KEY,
        StartDatetime DATETIME2(7) NOT NULL,
        EndDatetime DATETIME2(7) NOT NULL,
        DateFullName NVARCHAR(30) NOT NULL,
        DayOfWeekNumber TINYINT NOT NULL,
        DayOfWeekdayNumber TINYINT NOT NULL,
        DayCode INT NOT NULL,
        DayOFWeekNameShort NVARCHAR(4) NOT NULL,
        DayOFWeekNameLong NVARCHAR(9) NOT NULL,
        DayOfMonthNumber TINYINT NOT NULL,
        DayOfQuarterNumber TINYINT NOT NULL,
        DayOfYearNumber SMALLINT NOT NULL,
        WeekOfMonthNumber TINYINT NOT NULL,
        WeekOfQuarterNumber TINYINT NOT NULL,
        WeekOfYearNumber TINYINT NOT NULL,
        WeekStart DATE NOT NULL,
        WeekEnd DATE NOT NULL,
        WeekStartDatetime DATETIME2(7) NOT NULL,
        WeekEndDatetime DATETIME2(7) NOT NULL,
        WeekPercentComplete FLOAT NOT NULL,
        WeekPercentRemaining FLOAT NOT NULL,
        MonthNumber TINYINT NOT NULL,
        MonthCode INT NOT NULL,
        MonthNameLong NVARCHAR(9) NOT NULL,
        MonthNameShort NVARCHAR(9) NOT NULL,
        MonthYearNameLong NVARCHAR(15) NOT NULL,
        MonthYearNameShort NVARCHAR(15) NOT NULL,
        MonthStart DATE NOT NULL,
        MonthEnd DATE NOT NULL,
        MonthStartDatetime DATETIME2(7) NOT NULL,
        MonthEndDatetime DATETIME2(7) NOT NULL,
        MonthPercentComplete FLOAT NOT NULL,
        MonthPercentRemaining FLOAT NOT NULL,
        QuarterNumber TINYINT NOT NULL,
        QuarterStart DATE NOT NULL,
        QuarterEnd DATE NOT NULL,
        QuarterStartDatetime DATETIME2(7) NOT NULL,
        QuarterEndDatetime DATETIME2(7) NOT NULL,
        QuarterShort NVARCHAR(2) NOT NULL,
        QuarterLong NVARCHAR(9) NOT NULL,
        QuarterPercentComplete FLOAT NOT NULL,
        QuarterPercentRemaining FLOAT NOT NULL,
        YearNumber SMALLINT NOT NULL,
        YearStart DATE NOT NULL,
        YearEnd DATE NOT NULL,
        YearStartDatetime DATETIME2(7) NOT NULL,
        YearEndDatetime DATETIME2(7) NOT NULL,
        YearPercentComplete FLOAT NOT NULL,
        YearPercentRemaining FLOAT NOT NULL,
        WeekOfMonthOccurance TINYINT NOT NULL,
        WeekOfQuarterOccurance TINYINT NOT NULL,
        WeekOfYearOccurance TINYINT NOT NULL,
        IsWeekday TINYINT NOT NULL,
        IsWeekend TINYINT NOT NULL,
        IsHoliday TINYINT NOT NULL,
        HolidayName NVARCHAR(50) NULL,
        ModifiedDateTime DATETIME2(7) CONSTRAINT DF_Dates_ModifiedDateTime DEFAULT(SYSUTCDATETIME()) NOT NULL,
        [Version] ROWVERSION NOT NULL
        )
    GO
    
    CREATE UNIQUE NONCLUSTERED INDEX IX_Dates_StartDatetime_EndDatetime ON dbo.Dates (
        StartDatetime ASC,
        EndDatetime ASC
        )
    GO
    
    CREATE NONCLUSTERED INDEX IX_Dates_WeekStartDatetime_WeekEndDatetime ON dbo.Dates (
        WeekStartDatetime ASC,
        WeekEndDatetime ASC
        )
    GO
    
    CREATE NONCLUSTERED INDEX IX_Dates_MonthStartDatetime_MonthEndDatetime ON dbo.Dates (
        MonthStartDatetime ASC,
        MonthEndDatetime ASC
        )
    GO
    
    CREATE NONCLUSTERED INDEX IX_Dates_QuarterStartDatetime_QuarterEndDatetime ON dbo.Dates (
        QuarterStartDatetime ASC,
        QuarterEndDatetime ASC
        )
    GO
    
    CREATE NONCLUSTERED INDEX IX_Dates_YearStartDatetime_YearEndDatetime ON dbo.Dates (
        YearStartDatetime ASC,
        YearEndDatetime ASC
        )
    GO
    

    这是种子脚本:

    SET DATEFIRST 7;
    
    DECLARE @FDate DATE,
        @TDate DATE,
        @Now DATETIME2(7) = SYSUTCDATETIME();
    
    /******************************************************************************
    DATE RANGE TO BUILD TABLE DATA
    *******************************************************************************/
    
    SET @FDate = '1900-01-01';
    SET @TDate = '2099-12-31';
    
    /******************************************************************************
    DECLARE TABLE VARIABLES FOR WEEK / MONTH / QUARTER DATA POINTS
    *******************************************************************************/
    
    DECLARE @OccuranceMonth TABLE (
        FDate INT NOT NULL,
        TDate INT NOT NULL,
        Occurance INT NOT NULL,
        UNIQUE CLUSTERED (FDate,TDate)
    );
    
    INSERT INTO @OccuranceMonth
    VALUES
    (1,7,1),
    (8,14,2),
    (15,21,3),
    (22,28,4),
    (29,31,5);
    
    DECLARE @OccuranceQuarter TABLE (
        FDate INT NOT NULL,
        TDate INT NOT NULL,
        Occurance INT NOT NULL,
        UNIQUE CLUSTERED (FDate,TDate)
    );
    
    INSERT INTO @OccuranceQuarter
    VALUES
    (1,7,1),
    (8,14,2),
    (15,21,3),
    (22,28,4),
    (29,35,5),
    (36,42,6),
    (43,49,7),
    (50,56,8),
    (57,63,9),
    (64,70,10),
    (71,77,11),
    (78,84,12),
    (85,91,13),
    (92,98,14);
    
    DECLARE @OccuranceYear TABLE (
        FDate INT NOT NULL,
        TDate INT NOT NULL,
        Occurance INT NOT NULL,
        UNIQUE CLUSTERED (FDate,TDate)
    );
    
    INSERT INTO @OccuranceYear
    VALUES
    (1,7,1),
    (8,14,2),
    (15,21,3),
    (22,28,4),
    (29,35,5),
    (36,42,6),
    (43,49,7),
    (50,56,8),
    (57,63,9),
    (64,70,10),
    (71,77,11),
    (78,84,12),
    (85,91,13),
    (92,98,14),
    (99,105,15),
    (106,112,16),
    (113,119,17),
    (120,126,18),
    (127,133,19),
    (134,140,20),
    (141,147,21),
    (148,154,22),
    (155,161,23),
    (162,168,24),
    (169,175,25),
    (176,182,26),
    (183,189,27),
    (190,196,28),
    (197,203,29),
    (204,210,30),
    (211,217,31),
    (218,224,32),
    (225,231,33),
    (232,238,34),
    (239,245,35),
    (246,252,36),
    (253,259,37),
    (260,266,38),
    (267,273,39),
    (274,280,40),
    (281,287,41),
    (288,294,42),
    (295,301,43),
    (302,308,44),
    (309,315,45),
    (316,322,46),
    (323,329,47),
    (330,336,48),
    (337,343,49),
    (344,350,50),
    (351,357,51),
    (358,364,52),
    (365,371,53);
    
    /******************************************************************************
    CLEAR TABLE - YOU COULD CHANGE THE WHOLE THING INTO A MERGE
    *******************************************************************************/
    
    TRUNCATE TABLE dbo.Dates;
    
    /******************************************************************************
    USE RECURSION INSTEAD OF LOOP FOR DATE RANGE BASE
    *******************************************************************************/
    
    WITH DATES AS (
        SELECT
            @FDate AS DateId
        UNION ALL
        SELECT
            DATEADD(DD,1,DateId) AS DateId
        FROM DATES
        WHERE DATEADD(DD,1,DateId) <= @TDate
    )
    
    /******************************************************************************
    INSERT FINAL RESULTS
    *******************************************************************************/
    
    INSERT INTO dbo.Dates (
        DateId,
        StartDatetime,
        EndDatetime,
        DateFullName,
        DayOfWeekNumber,
        DayOfWeekdayNumber,
        DayCode,
        DayOFWeekNameShort,
        DayOFWeekNameLong,
        DayOfMonthNumber,
        DayOfQuarterNumber,
        DayOfYearNumber,
        WeekOfMonthNumber,
        WeekOfQuarterNumber,
        WeekOfYearNumber,
        WeekStart,
        WeekEnd,
        WeekStartDatetime,
        WeekEndDatetime,
        WeekPercentComplete,
        WeekPercentRemaining,
        MonthNumber,
        MonthCode,
        MonthNameLong,
        MonthNameShort,
        MonthYearNameLong,
        MonthYearNameShort,
        MonthStart,
        MonthEnd,
        MonthStartDatetime,
        MonthEndDatetime,
        MonthPercentComplete,
        MonthPercentRemaining,
        QuarterNumber,
        QuarterStart,
        QuarterEnd,
        QuarterStartDatetime,
        QuarterEndDatetime,
        QuarterShort,
        QuarterLong,
        QuarterPercentComplete,
        QuarterPercentRemaining,
        YearNumber,
        YearStart,
        YearEnd,
        YearStartDatetime,
        YearEndDatetime,
        YearPercentComplete,
        YearPercentRemaining,
        WeekOfMonthOccurance,
        WeekOfQuarterOccurance,
        WeekOfYearOccurance,
        IsWeekday,
        IsWeekend,
        IsHoliday,
        HolidayName
        )
    SELECT
        dte.DateId,
        CAST(dte.DateId AS DATETIME2(7)) AS StartDatetime,
        CAST(CAST(dte.DateId AS NVARCHAR(10)) + ' 23:59:59.9999999' AS DATETIME2(7)) AS EndDatetime,
        DATENAME(MONTH,dte.DateId) + ' ' + CAST(DAY(dte.DateId) AS NVARCHAR(2)) + ', ' + CAST(YEAR(dte.DateId) AS NVARCHAR(4)) AS DateFullName,
        DATEPART(DW,dte.DateId) AS DayOfWeekNumber,
        REPLACE(DATEPART(DW,dte.DateId) - 1, 6, 0) AS DayOfWeekdayNumber,
        CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + 
            CASE WHEN LEN(MONTH(dte.DateId)) = 1 THEN '0' + CAST(MONTH(dte.DateId) AS NVARCHAR(2)) ELSE CAST(MONTH(dte.DateId) AS NVARCHAR(2)) END + 
            CASE WHEN LEN(DAY(dte.DateId)) = 1 THEN '0' + CAST(DAY(dte.DateId) AS NVARCHAR(2)) ELSE CAST(DAY(dte.DateId) AS NVARCHAR(2)) END AS INT) AS DayCode,
        CASE DATENAME(WEEKDAY,dte.DateId)
            WHEN 'Thursday' THEN 'Thur'
            ELSE LEFT(DATENAME(WEEKDAY,dte.DateId),3)
        END AS DayOFWeekNameShort,
        DATENAME(WEEKDAY,dte.DateId) AS DayOFWeekNameLong,
        DAY(dte.DateId) AS DayOfMonthNumber,
        DATEDIFF(d,DATEADD(qq,DATEDIFF(qq,0,dte.DateId),0),dte.DateId) + 1 AS DayOfQuarterNumber,
        DATEPART(dy,dte.DateId) AS DayOfYearNumber,
        DATEPART(WEEK,dte.DateId) - DATEPART(WEEK,DATEADD(MM,DATEDIFF(MM,0,dte.DateId),0)) + 1 AS WeekOfMonthNumber,
        DATEDIFF(WEEK,DATEADD(QUARTER,DATEDIFF(QUARTER,0,dte.DateId),0),dte.DateId) + 1 AS WeekOfQuarterNumber,
        DATEPART(WEEK,dte.DateId) AS WeekOfYearNumber,
        DATEADD(DD,-DATEPART(DW,dte.DateId) + 1,dte.DateId) AS WeekStart,
        DATEADD(DD,-DATEPART(DW,dte.DateId) + 7,dte.DateId) AS WeekEnd,
        CAST(DATEADD(DD,-DATEPART(DW,dte.DateId) + 1,dte.DateId) AS DATETIME) AS WeekStartDatetime,
        CAST(CAST(DATEADD(DD,-DATEPART(DW,dte.DateId) + 7,dte.DateId) AS NVARCHAR(10)) + ' 23:59:59.9999999' AS DATETIME2(7)) AS WeekEndDatetime,
        CAST(DATEPART(DW,dte.DateId) AS FLOAT) / 7 AS WeekPercentComplete,
        1 - CAST(DATEPART(DW,dte.DateId) AS FLOAT) / 7 AS WeekPercentRemaining,
        MONTH(dte.DateId) AS MonthNumber,
        CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + CASE WHEN LEN(MONTH(dte.DateId)) = 1 THEN '0' + CAST(MONTH(dte.DateId) AS NVARCHAR(2)) ELSE CAST(MONTH(dte.DateId) AS NVARCHAR(2)) END AS INT) AS MonthCode,
        DATENAME(MONTH,dte.DateId) AS MonthNameLong,
        CASE 
            WHEN LEN(DATENAME(MONTH,dte.DateId)) = 4 THEN DATENAME(MONTH,dte.DateId)
            WHEN DATENAME(MONTH,dte.DateId) = 'September' THEN 'Sept'
            ELSE LEFT(DATENAME(MONTH,dte.DateId),3)
        END AS MonthNameShort,
        DATENAME(MONTH,dte.DateId) + ' ' + CAST(YEAR(dte.DateId) AS NVARCHAR(4)) AS MonthYearNameLong,
        CASE 
            WHEN LEN(DATENAME(MONTH,dte.DateId)) = 4 THEN DATENAME(MONTH,dte.DateId)
            WHEN DATENAME(MONTH,dte.DateId) = 'September' THEN 'Sept'
            ELSE LEFT(DATENAME(MONTH,dte.DateId),3)
        END + ' ' + CAST(YEAR(dte.DateId) AS NVARCHAR(4)) AS MonthYearNameShort,
        CAST(CAST(MONTH(dte.DateId) AS NVARCHAR(2)) + '-01-' + CAST(YEAR(dte.DateId) AS NVARCHAR(4)) AS DATE) AS MonthStart,
        DATEADD(DD,-1,DATEADD(MONTH,1,CAST(CAST(MONTH(dte.DateId) AS NVARCHAR(2)) + '-01-' + CAST(YEAR(dte.DateId) AS NVARCHAR(4)) AS DATE))) AS MonthEnd,
        CAST(CAST(CAST(MONTH(dte.DateId) AS NVARCHAR(2)) + '-01-' + CAST(YEAR(dte.DateId) AS NVARCHAR(4)) AS DATE) AS DATETIME) AS MonthStartDatetime,
        CAST(CAST(DATEADD(DD,-1,DATEADD(MONTH,1,CAST(CAST(MONTH(dte.DateId) AS VARCHAR(2)) + '-01-' + CAST(YEAR(dte.DateId) AS VARCHAR(4)) AS DATE))) AS NVARCHAR(10)) + ' 23:59:59.9999999' AS DATETIME2(7)) AS MonthEndDatetime,
        CAST(DAY(dte.DateId) AS FLOAT) / CAST(DAY(DATEADD(DD,-1,DATEADD(MONTH,1,CAST(CAST(MONTH(dte.DateId) AS NVARCHAR(2)) + '-01-' + CAST(YEAR(dte.DateId) AS NVARCHAR(4)) AS DATE)))) AS FLOAT) AS MonthPercentComplete,
        1 - (CAST(DAY(dte.DateId) AS FLOAT) / CAST(DAY(DATEADD(DD,-1,DATEADD(MONTH,1,CAST(CAST(MONTH(dte.DateId) AS NVARCHAR(2)) + '-01-' + CAST(YEAR(dte.DateId) AS NVARCHAR(4)) AS DATE)))) AS FLOAT)) AS MonthPercentRemaining,
        DATENAME(QQ,dte.DateId) AS QuarterNumber,
        CAST(DATEADD(q,DATEDIFF(q,0,dte.DateId),0) AS DATE) AS QuarterStart,
        CAST(DATEADD(d,-1,DATEADD(q,DATEDIFF(q,0,dte.DateId)+1,0)) AS DATE) AS QuarterEnd,
        CAST(CAST(DATEADD(q,DATEDIFF(q,0,dte.DateId),0) AS DATE) AS DATETIME) AS QuarterStartDatetime,
        CAST(CAST(CAST(DATEADD(d,-1,DATEADD(q,DATEDIFF(q,0,dte.DateId)+1,0)) AS DATE) AS NVARCHAR(10)) + ' 23:59:59.9999999' AS DATETIME2(7)) AS QuarterEndDatetime,
        'Q' + DATENAME(QQ,dte.DateId) AS QuarterShort,
        'Quarter ' + DATENAME(QQ,dte.DateId) AS QuarterLong,
        CAST(DATEDIFF(d,DATEADD(qq,DATEDIFF(qq,0,dte.DateId),0),dte.DateId) + 1 AS FLOAT) / CAST(DATEDIFF(DD,CAST(DATEADD(q,DATEDIFF(q,0,dte.DateId),0) AS DATE),CAST(DATEADD(d,-1,DATEADD(q,DATEDIFF(q,0,dte.DateId)+1,0)) AS DATE)) + 1 AS FLOAT) AS QuarterPercentComplete,
        1 - (CAST(DATEDIFF(d,DATEADD(qq,DATEDIFF(qq,0,dte.DateId),0),dte.DateId) + 1 AS FLOAT) / CAST(DATEDIFF(DD,CAST(DATEADD(q,DATEDIFF(q,0,dte.DateId),0) AS DATE),CAST(DATEADD(d,-1,DATEADD(q,DATEDIFF(q,0,dte.DateId)+1,0)) AS DATE)) + 1 AS FLOAT)) AS QuarterPercentRemaining,
        YEAR(dte.DateId) AS YearNumber,
        CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + '-01-01' AS DATE) AS YearStart,
        CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + '-12-31' AS DATE) AS YearEnd,
        CAST(CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + '-01-01' AS DATE) AS DATETIME) AS YearStartDatetime,
        CAST(CAST(CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + '-12-31' AS DATE) AS NVARCHAR(10)) + ' 23:59:59.9999999' AS DATETIME2(7)) AS YearEndDatetime,
        CAST(DATEPART(dy,dte.DateId) AS FLOAT) / CAST(DATEDIFF(DD,CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + '-01-01' AS DATE),CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + '-12-31' AS DATE)) + 1 AS FLOAT) AS YearPercentComplete,
        1 - (CAST(DATEPART(dy,dte.DateId) AS FLOAT) / CAST(DATEDIFF(DD,CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + '-01-01' AS DATE),CAST(CAST(YEAR(dte.DateId) AS NVARCHAR(4)) + '-12-31' AS DATE)) + 1 AS FLOAT)) AS YearPercentRemaining,
        a.Occurance AS WeekOfMonthOccurance,
        b.Occurance AS WeekOfQuarterOccurance,
        c.Occurance AS WeekOfYearOccurance,
        CASE
            WHEN DATEPART(DW,dte.DateId) BETWEEN 2 AND 6 THEN 1
            ELSE 0
        END AS IsWeekday,
        CASE
            WHEN DATEPART(DW,dte.DateId) IN (1,7) THEN 1
            ELSE 0
        END AS IsWeekend,
        0 AS IsHoliday,
        NULL AS HolidayName
    FROM DATES AS dte
    LEFT JOIN @OccuranceMonth AS a
        ON 1 = 1
        AND DAY(dte.DateId) BETWEEN a.FDate AND a.TDate
    LEFT JOIN @OccuranceQuarter AS b
        ON 1 = 1
        AND DATEDIFF(d,DATEADD(qq,DATEDIFF(qq,0,dte.DateId),0),dte.DateId) + 1 BETWEEN b.FDate AND b.TDate
    LEFT JOIN @OccuranceYear AS c
        ON 1 = 1
        AND DATEPART(dy,dte.DateId) BETWEEN c.FDate AND c.TDate
    OPTION (MAXRECURSION 0);
    
    /******************************************************************************
    HOLIDAY FLAGGING
    *******************************************************************************/
    
    -- New Year's Day
    
    UPDATE dte
    SET dte.IsHoliday = 1,
        dte.HolidayName = 'New Year''s Day',
        dte.ModifiedDateTime = @Now
    FROM dbo.Dates AS dte
    WHERE MONTH(dte.DateId) = 1
        AND DAY(dte.DateId) = 1
        AND dte.IsHoliday = 0;
    
    -- President's Day
    
    UPDATE dte
    SET dte.IsHoliday = 1,
        dte.HolidayName = 'President''s Day',
        dte.ModifiedDateTime = @Now
    FROM dbo.Dates AS dte
    WHERE MONTH(dte.DateId) = 2
        AND dte.WeekOfMonthOccurance = 3
        AND dte.DayOfWeekNumber = 2
        AND dte.IsHoliday = 0;
    
    -- Memorial Day
    
    UPDATE dte
    SET dte.IsHoliday = 1,
        dte.HolidayName = 'Memorial Day',
        dte.ModifiedDateTime = @Now
    FROM dbo.Dates AS dte
    WHERE MONTH(dte.DateId) = 5
        AND DAY(dte.DateId) BETWEEN 25 AND 31
        AND dte.DayOfWeekNumber = 2
        AND dte.IsHoliday = 0;
    
    -- Independence Day
    
    UPDATE dte
    SET dte.IsHoliday = 1,
        dte.HolidayName = 'Independence Day',
        dte.ModifiedDateTime = @Now
    FROM dbo.Dates AS dte
    WHERE MONTH(dte.DateId) = 7
        AND DAY(dte.DateId) = 4
        AND dte.IsHoliday = 0;
    
    -- Labor Day
    
    UPDATE dte
    SET dte.IsHoliday = 1,
        dte.HolidayName = 'Labor Day',
        dte.ModifiedDateTime = @Now
    FROM dbo.Dates AS dte
    WHERE MONTH(dte.DateId) = 9
        AND dte.DayOfWeekNumber = 2
        AND dte.WeekOfMonthOccurance = 1
        AND dte.IsHoliday = 0;
    
    --Veteran's Day
    
    UPDATE dte
    SET dte.IsHoliday = 1,
        dte.HolidayName = 'Veteran''s Day',
        dte.ModifiedDateTime = @Now
    FROM dbo.Dates AS dte
    WHERE MONTH(dte.DateId) = 11
        AND DAY(dte.DateId) = 11
        AND dte.IsHoliday = 0;
    
    -- Thanksgiving Day
    
    UPDATE dte
    SET dte.IsHoliday = 1,
        dte.HolidayName = 'Thanksgiving Day',
        dte.ModifiedDateTime = @Now
    FROM dbo.Dates AS dte
    WHERE MONTH(dte.DateId) = 11
        AND dte.WeekOfMonthOccurance = 4
        AND dte.DayOfWeekNumber = 5
        AND dte.IsHoliday = 0;
    
    -- Black Friday
    
    UPDATE dte
    SET dte.IsHoliday = 1,
        dte.HolidayName = 'Black Friday',
        dte.ModifiedDateTime = @Now
    FROM dbo.Dates AS dte
    WHERE MONTH(dte.DateId) = 11
        AND dte.WeekOfMonthOccurance = 4
        AND dte.DayOfWeekNumber = 6
        AND dte.IsHoliday = 0;
    
    -- Christmas Day'
    
    UPDATE dte
    SET dte.IsHoliday = 1,
        dte.HolidayName = 'Christmas Day',
        dte.ModifiedDateTime = @Now
    FROM dbo.Dates AS dte
    WHERE MONTH(dte.DateId) = 12
        AND DAY(dte.DateId) = 25
        AND dte.IsHoliday = 0;
    

    以下是一些示例脚本(还有每天/每周/每月/每年的开始和结束日期时间列):

    DECLARE @BaseDate DATE,
        @FromDate DATE,
        @ToDate DATE;
    
    SET @BaseDate = SYSUTCDATETIME();
    
    /******************************************************************************
    THIS IS WHERE YOU WOULD FETCH A SPECIFIC DATE TO GET ALL KINDS OF INFO ON IT.
    A DATE DIMENSION IS ESPECIALLY USEFUL WHEN CREATING REPORTS.
    *******************************************************************************/
    
    SELECT
        @FromDate = dte.MonthStart,
        @ToDate = dte.MonthEnd
    FROM dbo.Dates AS dte
    WHERE dte.DateId = @BaseDate;
    
    SELECT *
    FROM TBL_A
    WHERE COLUMN_A BETWEEN @FromDate AND @ToDate;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-23
      • 2013-09-12
      相关资源
      最近更新 更多