【问题标题】:SQL Server : WHERE clause to only return values from a range of last day of monthsSQL Server:WHERE 子句仅返回月份最后一天范围内的值
【发布时间】:2017-10-09 03:29:39
【问题描述】:

我有一个名为theTable 的表,我想从中导入一些数据。 theTable 包括产品库存值,我只对查找 6 个月内每个月最后一天的库存余额感兴趣。

我有一个名为DateKey 的列,它看起来像yyyymmdd,描述了记录库存余额的日期。

例如,我希望能够在DateKey 值处推断出stockValue20160131,20160331

为此我已经尝试过:

CREATE TABLE #theTable
(
    DateKey INT,
    stockValue INT
);

INSERT INTO #theTable
VALUES (20160131, 4), (20160130, 5),
       (20160312, 5), (20160331, 4);

SELECT DateKey, stockValue 
FROM #theTable
WHERE DateKey BETWEEN CONVERT(VARCHAR(8), DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 16, 0), 112)
                  AND CONVERT(VARCHAR(8), DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()) - 13, -1), 112)

(我添加了 convert() 恶作剧以避免 DateKey 不是DateTime 类型的错误)

但这(自然)返回:

DateKey     stockValue
20160131    4
20160130    5
20160312    5
20160331    4

我怎样才能调整这条 SQL 语句只包括:

DateKey     stockValue
20160131    4
20160331    4

即在我指定的日期范围内几个月的最后几天?

编辑

问题是是否有一种方法可以只获取最后一天的值而不必硬编码“WHERE DATEKEY IN ('20160131','20160228','20160331') 因为会有很多不同的值 I'我想从中进行选择,这会使硬编码的解决方案变得非常容易出错和耗时。

【问题讨论】:

  • 为什么datekey首先不是date类型?由于您似乎只是在寻找当月的最后一天,您是否检查了EOMONTH() 函数?
  • 快速谷歌搜索产生了重复页面。你有没有努力自己解决这个问题?
  • @TabAlleman 我发现了几个线程,它们回答了如何找到一个月的最后一天的问题。我没有找到一种方法来结合“之间”使用它,因为它仍然会在两个月的最后一天之间获得每个日期。特别是在要过滤的列不是 DateTime 类型的情况下。
  • @alroc 它不是 DateTime 类型,因为它用于浏览和创建一个大立方体,我不希望这样的键不是整数类型的情况。 EOMONTH() 是一个非常有趣的函数。我之前已经阅读过它,但是如果您的列不是 DateTime 类型,我没有掌握必须进行的转换才能使用它。

标签: sql sql-server date sql-server-2016


【解决方案1】:

使用EOMONTH 函数并仅获取此类行。

SELECT DateKey, stockValue 
FROM #theTable
where CONVERT(date, convert(varchar(10), datekey)) = eomonth(CONVERT(date, convert(varchar(10), datekey)))

【讨论】:

  • 感谢您的回答。我之前曾摆弄过 EOMONTH,但我认为我确实过度考虑了实现,由于某种原因,我发现使用不是 DateTime 类型的 DateKey 很难实现。但是这个解决方案真的很优雅。
【解决方案2】:

这会给你当月的月底:

FORMAT(EOMONTH(GETDATE()), 'yyyyMMdd')

这给了你 2 个月前的月底:

FORMAT(EOMONTH(DATEADD(MONTH, -2, GETDATE())), 'yyyyMMdd')

【讨论】:

    【解决方案3】:
    SELECT DateKey, stockValue 
    FROM #theTable
    WHERE DateKey  = 
    DATEADD(month, ((YEAR(DateKey) - 1900) * 12) + MONTH(DateKey), -1)
    

    【讨论】:

      【解决方案4】:

      假设您不能保证最后一个日期键将是该月的最后一天

      这会起作用

      create table #theTable(
      DateKey int,
      stockValue int
      );
      
      insert into #theTable
      VALUES(20160131,4),
      (20160130,5),
      (20160312,5),
      (20160331,4);
      
      ;with lastDayOfMonth as (
      select 
      max(DateKey) as MaxDate
      from #theTable
      group by left(cast(DateKey as varchar(8)),6))
      
      SELECT DateKey, stockValue ,left(cast(DateKey as varchar(8)),6) 
      FROM #theTable
      inner join lastDayOfMonth
      on MaxDate = DateKey
      WHERE DateKey between convert(varchar(8),DATEADD(month,datediff(month,0,getdate())-16,0),112)
      and CONVERT(VARCHAR(8),DATEADD(MONTH, DATEDIFF(month, -1, getdate())-13,-1),112)
      
      drop table #theTable
      

      【讨论】:

        【解决方案5】:

        你可以使用 eomonth() 如下

        select * from #thetable where 
        convert(date,convert(varchar(8), DateKey,112)) = eomonth(convert(date, convert(varchar(8), datekey,112))) 
        

        输出:

        +----------+------------+
        | DateKey  | stockValue |
        +----------+------------+
        | 20160131 |          4 |
        | 20160331 |          4 |
        +----------+------------+
        

        【讨论】:

          【解决方案6】:

          您可以使用 EOMONTH (https://docs.microsoft.com/en-us/sql/t-sql/functions/eomonth-transact-sql) 来检查日期是否是该月的最后一个日期。

          类似这样的:

          create table #theTable(
          DateKey int,
          stockValue int
          );
          
          insert into #theTable
          VALUES(20160131,4),
          (20160130,5),
          (20160312,5),
          (20160331,4);
          
          
          SELECT DateKey, stockValue 
          FROM #theTable
          WHERE DateKey between convert(varchar(8),DATEADD(month,datediff(month,0,getdate())-16,0),112)
          and CONVERT(VARCHAR(8),DATEADD(MONTH, DATEDIFF(month, -1, getdate())-13,-1),112)
          AND EOMONTH ( CONVERT(varchar(8),datekey) ) = CONVERT(varchar(8),datekey)
          
          
          DROP TABLE #theTable
          

          【讨论】:

            猜你喜欢
            • 2011-08-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-01-05
            • 1970-01-01
            • 2013-06-24
            相关资源
            最近更新 更多