【问题标题】:How to get the last day for each month in a distinct year based on a field如何根据字段获取不同年份中每个月的最后一天
【发布时间】:2018-02-26 20:48:36
【问题描述】:
SELECT [ItemKey]
  ,[Location]
  ,[QtyOnHand]
  ,[UpdatedOnHandQty]
  ,AffectedDate
  FROM [Test].[dbo].[INCos]
  where ItemKey = '20406' 
  order by ItemKey, year(AffectedDate)

结果如下:

ItemKey UpdatedOnHandQty    AffectedDate
20406   1594.03            2013-12-27 00:00:00.000
20406   78.975            2014-09-15 00:00:00.000
20406   1401.975          2014-09-26 00:00:00.000
20406   512.261           2014-10-20 00:00:00.000
20406   849.928         2014-01-06 00:00:00.000
20406   842.132       2014-01-09 00:00:00.000
20406   1283.132      2014-02-05 00:00:00.000
20406   539.03        2014-02-11 00:00:00.000
20406   980.03       2014-05-07 00:00:00.000
20406   486.183      2014-05-12 00:00:00.000
20406   927.183      2014-06-03 00:00:00.000
20406   917.86       2014-06-27 00:00:00.000
20406   927.043     2014-07-18 00:00:00.000
20406   432.209     2014-07-18 00:00:00.000
20406   1314.209    2014-07-29 00:00:00.000

我想要的是每年只提取每个月最后一天的记录。我已经看到很多解决方案,我可以根据 GetDate() 获得每个月的最后一天,但我不需要。我只需要根据 AffectedDate 字段提取每年每个月的最后一条记录。

【问题讨论】:

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


    【解决方案1】:

    一个快速的选择是使用 WITH TIES 子句与 Row_Number()

    示例

    Select Top 1 with Ties * 
     From  YourTable
     where ItemKey = '20406' 
     Order by Row_Number() over (Partition by ItemKey,Year(AffectedDate),Month(AffectedDate) Order by AffectedDate Desc)
    

    退货

    ItemKey UpdatedOnHandQty    AffectedDate
    20406   1594.03             2013-12-27 00:00:00.000
    20406   842.132             2014-01-09 00:00:00.000
    20406   539.03              2014-02-11 00:00:00.000
    20406   486.183             2014-05-12 00:00:00.000
    20406   917.86              2014-06-27 00:00:00.000
    20406   1314.209            2014-07-29 00:00:00.000
    20406   1401.975            2014-09-26 00:00:00.000
    20406   512.261             2014-10-20 00:00:00.000
    

    【讨论】:

    • 我已经阅读了整个 Murch SQl Server 2012 开发书籍,但我从未听说过有关系。太感谢了。我已经为此工作了相当长的时间,这只是救了我。
    • @Ezzy 这就是我喜欢 SO 的原因。我每天都学到一些东西。乐意效劳。仅供参考 - 性能与 CTE 基本相同,但没有额外字段。
    • 是的,我同意。再次感谢你。这很有帮助。
    • 我认为 row_number() 没有关系。它基本上将 1 分配给任何 #1。 RANK() 不是更好吗?
    • 赞成,如果你有一张大桌子,请注意性能
    【解决方案2】:
    WITH CTE
     AS (SELECT Row_number()
                  OVER (
                    partition BY Month(AffectedDate)
                    ORDER BY AffectedDate DESC) rn,
                [ItemKey],
                [Location],
                [QtyOnHand],
                [UpdatedOnHandQty],
                AffectedDate
           FROM [Test].[dbo].[INCos]
          WHERE ItemKey = '20406')
    SELECT *
      FROM CTE
     WHERE rn = 1 
    

    【讨论】:

      【解决方案3】:

      这是另一个带有完整示例的选项,它有很多行,速度很快,希望这对你有用

          CREATE TABLE #DATA(
      ItemKey INT,
      UpdatedOnHandQty DECIMAL(16,2),
      AffectedDate DATETIME
      )
      INSERT INTO #DATA
      
      SELECT 20406   ,1594.03            ,'2013-12-27 00:00:00.000' UNION
      SELECT 20406   ,78.975            ,'2014-09-15 00:00:00.000' UNION
      SELECT 20406   ,1401.975          ,'2014-09-26 00:00:00.000' UNION
      SELECT 20406   ,512.261           ,'2014-10-20 00:00:00.000' UNION
      SELECT 20406   ,849.928         ,'2014-01-06 00:00:00.000' UNION
      SELECT 20406   ,842.132       ,'2014-01-09 00:00:00.000' UNION
      SELECT 20406   ,1283.132      ,'2014-02-05 00:00:00.000' UNION
      SELECT 20406   ,539.03        ,'2014-02-11 00:00:00.000' UNION
      SELECT 20406   ,980.03       ,'2014-05-07 00:00:00.000' UNION
      SELECT 20406   ,486.183      ,'2014-05-12 00:00:00.000' UNION
      SELECT 20406   ,927.183      ,'2014-06-03 00:00:00.000' UNION
      SELECT 20406   ,917.86       ,'2014-06-27 00:00:00.000' UNION
      SELECT 20406   ,927.043     ,'2014-07-18 00:00:00.000' UNION
      SELECT 20406   ,432.209     ,'2014-07-18 00:00:00.000' UNION
      SELECT 20406   ,1314.209    ,'2014-07-29 00:00:00.000'
      
      
      
      
      SELECT *
      FROM #DATA AS d
      WHERE d.ItemKey = 20406
      and EXISTS(
      SELECT TOP 1 1 FROM #DATA AS d1
      WHERE D1.ItemKey = d.ItemKEy
      AND YEAR(d.AffectedDate) = YEAR(d1.AffectedDate)
      AND MONTH(d.AffectedDate)= MONTH(d1.AffectedDate)
      GROUP BY  YEAR(d1.AffectedDate),MONTH(d1.AffectedDate)
      HAVING  MAX(d1.AffectedDate) = d.AffectedDate
      )
      ORDER BY d.AffectedDate desc
      
      
      DROP TABLE  #DATA
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-03
        • 2017-10-29
        • 2014-11-21
        • 2018-11-23
        • 2020-03-20
        相关资源
        最近更新 更多