【问题标题】:SQL Server: SELECT only the rows with MAX(DATE)SQL Server:仅选择具有 MAX(DATE) 的行
【发布时间】:2011-10-30 09:31:15
【问题描述】:

我有一个数据表(数据库是 MSSQL):

ID  OrderNO  PartCode  Quantity DateEntered
417 2144     44917     100      18-08-11
418 7235     11762     5        18-08-11
419 9999     60657     100      18-08-11
420 9999     60657     90       19-08-11

我想做一个返回 OrderNO、PartCode 和 Quantity 的查询,但只针对最后注册的订单。

我想从示例表中获取以下信息:

 OrderNO  PartCode  Quantity     
 2144     44917     100      
 7235     11762     5        
 9999     60657     90  

请注意,订单 9999 只返回了一行。

谢谢!

【问题讨论】:

  • 从您的评论中选择 ROW_NUMBER() 答案。它可能看起来更长,但根据我的经验,在适当的索引下它是最快的。
  • 感谢 Dems,感谢您的努力。
  • @GEMI 只是出于好奇,MAX(DATE) 不会为订单 9999 返回一行吗?
  • 是的,但我希望每个不同的订单只返回最后一个订单行。

标签: sql-server select max


【解决方案1】:

这对我来说非常好。

    select name, orderno from (
         select name, orderno, row_number() over(partition by 
           orderno order by created_date desc) as rn from orders
    ) O where rn =1;

【讨论】:

  • 除了缩进之外,这与 Mikael Eriksson 的回答没有任何区别。
【解决方案2】:

这对我有用。使用 MAX(CONVERT(date, ReportDate)) 确保您有日期值

select max( CONVERT(date, ReportDate)) FROM [TraxHistory]

【讨论】:

    【解决方案3】:

    如果你有索引 ID 和 OrderNo 你可以使用 IN:(我讨厌交易简单化,只是为了节省一些周期):

    select * from myTab where ID in(select max(ID) from myTab group by OrderNo);
    

    【讨论】:

      【解决方案4】:

      rownumber() over(...) 正在工作,但我不喜欢这个解决方案有两个原因。 - 当您使用 SQL2000 等旧版 SQL 时,此功能不可用 - 依赖于函数,不可读。

      另一种解决方案是:

      SELECT tmpall.[OrderNO] ,
             tmpall.[PartCode] ,
             tmpall.[Quantity] ,
      FROM   (SELECT [OrderNO],
                     [PartCode],
                     [Quantity],
                     [DateEntered]
              FROM   you_table) AS tmpall
             INNER JOIN (SELECT [OrderNO],
                                Max([DateEntered]) AS _max_date
                         FROM   your_table
                         GROUP  BY OrderNO ) AS tmplast
                     ON tmpall.[OrderNO] = tmplast.[OrderNO]
                        AND tmpall.[DateEntered] = tmplast._max_date
      

      【讨论】:

        【解决方案5】:

        尽量避免IN使用JOIN

        SELECT SQL_CALC_FOUND_ROWS *  FROM (SELECT  msisdn, callid, Change_color, play_file_name, date_played FROM insert_log
           WHERE play_file_name NOT IN('Prompt1','Conclusion_Prompt_1','silent')
         ORDER BY callid ASC) t1 JOIN (SELECT MAX(date_played) AS date_played FROM insert_log GROUP BY callid) t2 ON t1.date_played=t2.date_played
        

        【讨论】:

        【解决方案6】:
        select OrderNo,PartCode,Quantity
        from dbo.Test t1
        WHERE EXISTS(SELECT 1
                 FROM dbo.Test t2
                 WHERE t2.OrderNo = t1.OrderNo
                   AND t2.PartCode = t1.PartCode
                 GROUP BY t2.OrderNo,
                          t2.PartCode
                 HAVING t1.DateEntered = MAX(t2.DateEntered))
        

        这是上面提供的所有查询中最快的。查询成本为 0.0070668。

        上面的首选答案,由 Mikael Eriksson 提供,查询成本为 0.0146625

        您可能不关心这么小的样本的性能,但在大型查询中,这一切都会加起来。

        【讨论】:

        • 在我看来,这在大约 350 万行数据集上比这里的其他解决方案要快一些,但是 SSMS 建议使用一个可以将执行时间减半的索引。谢谢!
        • 快速直接。谢谢。
        • 我有 100k 行,对我来说 Mikael Eriksson 的查询快了 3 倍。也许是因为我在partition by子句中有ROUND函数。
        • 如果您的日期字段具有相同的值 (04/15/2017) 用于 2 个不同的 ID,它将返回 2 行...
        • 是的 Portekoi,这是真的,但是没有任何其他方法来区分这两行,你怎么能选择一个而不是另一个?您可以在结果上放置一个 TOP,但您怎么知道它不是您想要的另一行?
        【解决方案7】:

        您也可以使用该选择语句作为左连接查询... 示例:

        ... left join (select OrderNO,
           PartCode,
           Quantity from (select OrderNO,
                 PartCode,
                 Quantity,
                 row_number() over(partition by OrderNO order by DateEntered desc) as rn
          from YourTable) as T where rn = 1 ) RESULT on ....
        

        希望这对搜索此内容的人有所帮助:)

        【讨论】:

          【解决方案8】:

          如果您可以使用ROW_NUMBER(),最好的方法是 Mikael Eriksson。

          根据 Cularis 的回答,下一个最好的方法是加入查询。

          另外,最简单直接的方法是在 WHERE 子句中使用相关子查询。

          SELECT
            *
          FROM
            yourTable AS [data]
          WHERE
            DateEntered = (SELECT MAX(DateEntered) FROM yourTable WHERE orderNo = [data].orderNo)
          

          或者……

          WHERE
            ID = (SELECT TOP 1 ID FROM yourTable WHERE orderNo = [data].orderNo ORDER BY DateEntered DESC)
          

          【讨论】:

            【解决方案9】:

            如果您可以使用rownumber() over(...) ....

            select OrderNO,
                   PartCode,
                   Quantity
            from (select OrderNO,
                         PartCode,
                         Quantity,
                         row_number() over(partition by OrderNO order by DateEntered desc) as rn
                  from YourTable) as T
            where rn = 1      
            

            【讨论】:

            • 感谢 Mikael Eriksson,这是一个很棒的查询!
            【解决方案10】:

            对于 MySql,您可以执行以下操作:

            select OrderNO, PartCode, Quantity from table a
            join (select ID, MAX(DateEntered) from table group by OrderNO) b on a.ID = b.ID
            

            【讨论】:

            • 按订单号分组不能在内表中选择ID
            • @Dems 谢谢@cularis 是的,这里指的是MySql,问题没有说明是什么数据库引擎
            • 如果您发布代码、XML 或数据示例,在文本编辑器中突出显示这些行并单击编辑器上的“代码示例”按钮 ({ })工具栏以很好地格式化和语法突出显示它!
            • 这是 MSSQL,抱歉。
            【解决方案11】:
            SELECT t1.OrderNo, t1.PartCode, t1.Quantity
            FROM table AS t1
            INNER JOIN (SELECT OrderNo, MAX(DateEntered) AS MaxDate
                        FROM table
                        GROUP BY OrderNo) AS t2
            ON (t1.OrderNo = t2.OrderNo AND t1.DateEntered = t2.MaxDate)
            

            内部查询选择所有OrderNo 及其最大日期。要获取表格的其他列,您可以在 OrderNoMaxDate 上加入它们。

            【讨论】:

              猜你喜欢
              • 2023-03-14
              • 1970-01-01
              • 2018-02-16
              • 1970-01-01
              • 1970-01-01
              • 2021-10-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多