将WHERE子句转换为CASE表达式

时间:2018-09-20 17:36:35

标签: sql-server case datediff dateadd getdate

有人可以帮助我使用CASE(使用易于阅读的语法)重写此代码吗:

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

2 个答案:

答案 0 :(得分:0)

创建日期维度实际上可以简化这样的事情;特别是如果您想为会计月份或其他内容添加列。从表中提取日期标签或值,将它们分配给变量,然后在查询中使用它们。更轻松,更清洁。更少的错误空间。可以肯定此查询是可靠的,但是如果您决定使用它,则应审核一些记录。

这是桌子:

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;

答案 1 :(得分:0)

在where子句中使用case expression只是使其变得更易于阅读。您将需要熟悉包含dateadd()datediff()函数的T-SQL中的日期处理。另外,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返回: 因为我们为此添加了0天到零日期: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

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

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"实际的月末是之后,不是 strong> 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中的时间精度(即数据类型:日期,smalldatetime,datetime或datetime2)

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