检查日期是否在月份和年份范围内

时间:2017-09-26 20:06:04

标签: sql-server sql-server-2008 tsql

如果用户选择范围,例如:

  • 开始时间:2016年11月
  • 结束:2017年9月,

我希望包括2016-11-01至2017-09-30范围内的所有结果。

我尝试将年,月和日连在一起,但问题是并非所有月份都有相同的最后一天。虽然我知道所有月份都是从第01天开始,但是一个月的结束日可能是28,29,30或31。

如果没有构建日期,有没有办法做到这一点? SqlServer 2008没有EOMONTH功能,我觉得比这更复杂的东西不是正确的解决方案。我想避免这个:

WHERE
    DateCol >= '2016' + '-' + '11' + '-01' AND
    DateCol <= '2017' + '-' + '09' + '-30'

6 个答案:

答案 0 :(得分:1)

在我看来,最简单和最好的答案是从月初的第一个月到月末的第一个月,并使第二个比较不包括在内。

换句话说,而不是:

WHERE
    DateCol >= '2016' + '-' + '11' + '-01' AND
    DateCol <= '2017' + '-' + '09' + '-30'

就是这样:

WHERE
    DateCol >= '2016' + '-' + '11' + '-01' AND
    DateCol < '2017' + '-' + '10' + '-01'

答案 1 :(得分:1)

有一种更快的方法:

DECLARE @minDate DATE
DECLARE @maxDate DATE
SET @minDate = XXXXX
SET @maxDate =  YYYYY

-- Get the first day of the month minDate.
SET @minDate = CONVERT(datetime,CONVERT(varchar(6),@minDate,112)+'01',112)
-- Get the last day of the month minDate.
SET @maxDate = CONVERT(datetime,CONVERT(varchar(6),@maxDate,112)+'01',112)
SET @maxDate = DATEADD(day, -1, DATEADD(month, 1, @maxDate))


SELECT * FROM myTABLE WHERE DateCol >= @minDate AND DateCol <= @maxDate

或者:

SELECT * FROM myTABLE
WHERE DateCol >= CONVERT(datetime,CONVERT(varchar(6),XXXXX,112)+'01',112)
  AND DateCol <= DATEADD(day, -1, DATEADD(month, 1, CONVERT(datetime,CONVERT(varchar(6),YYYYY,112)+'01',112)))

对于XXXXX和YYYYY使用CONVERT(datetime,&#39; 20170930&#39;,112)或CONVERT(datetime,&#39; 09-30-2017&#39;,110)等语法而不是&#39 ; 2017年9月30日&#39;使用 SQL Server隐式转换从char到datetime(依赖于服务器配置:可能是危险的!)。

使用此语法更快,因为@minDate和@maxDate不需要任何评估。这样索引可以直接使用......

否则,模拟eomonth()行为的标量函数可能很有用......

答案 2 :(得分:0)

对于2008年,您只需转换字符串

即可

示例

Select Date1=convert(date,'November 2016')
      ,Date2=dateadd(DAY,-1,dateadd(MONTH,1,convert(date,'September 2017')))

<强>返回

Date1       Date2
2016-11-01  2017-09-30

所以WHERE将是这样的事情

 ...
 Where DateCol between convert(date,'November 2016')
                  and dateadd(DAY,-1,dateadd(MONTH,1,convert(date,'September 2017')))

答案 3 :(得分:0)

您可以使用以下select语句通过向其传递字段或日期来获取任何月份(和任何年份)的最后日期:

DECLARE @dtDate DATE
SET @dtDate = '09/25/2016'
SELECT CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@dtDate)+1,0)) AS DATE) AS LastDay_AnyMonth

请提供一些示例数据和所需结果,我会进一步更新我的答案。

答案 4 :(得分:0)

你走了:

DECLARE @YourTable TABLE (YourData DATE);


INSERT INTO @YourTable VALUES
('2016-11-01'),
('2016-09-05'),
('2017-03-03'),
('2017-11-11'),
('2017-12-14'),
('2017-09-30');

WITH CTE AS (
    SELECT YourData
    FROM @YourTable
    WHERE YEAR(YourData) =2016 AND MONTH (YourData) >= 11
    )
    SELECT YourData 
    FROM @YourTable
    WHERE YEAR(YourData) =2017 AND MONTH (YourData) <= 9
    UNION ALL
    SELECT YourData
    FROM CTE;

无需知道月末(28或30或31)。

答案 5 :(得分:0)

用于执行基于日期的操作的有用构造是使用Date Dimension表。您正在创建一个查找表,其中填充了大量有关日期的信息。然后,您可以根据您拥有的信息查询表。该表足够小,因此不会产生重大的性能问题。

在您的特定情况下,您有月份和年份。您可以将其插入到日期维度表中,以获取从月份开始的月份中的第一个月份以及从结束月份开始的月份中的最后一个月份。现在,您可以在没有任何复杂逻辑或计算的情况下搜索时间范围。

Aaron Bertrand在此深入解释:https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/