【问题标题】:Fetch the row which has the Max value for a column获取列的最大值所在的行
【发布时间】:2010-09-12 09:24:42
【问题描述】:

表:

UserId, Value, Date.

我想获取每个 UserId 的用户 ID,最大值(日期)的值。也就是说,每个具有最新日期的 UserId 的值。有没有办法简单地在 SQL 中做到这一点? (最好是甲骨文)

更新:对任何含糊之处表示歉意:我需要获取所有 UserId。但是对于每个 UserId,只有该用户具有最新日期的那一行。

【问题讨论】:

标签: sql oracle greatest-n-per-group


【解决方案1】:

我认为是这样的。 (请原谅我的任何语法错误;我已经习惯了使用 HQL!)

编辑:也误读了这个问题!更正了查询...

SELECT UserId, Value
FROM Users AS user
WHERE Date = (
    SELECT MAX(Date)
    FROM Users AS maxtest
    WHERE maxtest.UserId = user.UserId
)

【讨论】:

  • 不满足“for each UserId”条件
  • 哪里会失败?对于 Users 中的每个 UserID,将保证至少返回包含该 UserID 的一行。还是我在某处遗漏了一个特殊情况?
【解决方案2】:

我不知道您的确切列名,但应该是这样的:

选择用户名,值 来自用户 u1 其中日期 =(选择最大值(日期) 来自用户 u2 其中 u1.userid = u2.userid)

【讨论】:

  • 可能效率不高,史蒂夫。
  • 您可能低估了 Oracle 查询优化器。
  • 一点也不。这几乎肯定会被实现为使用嵌套循环连接来获取日期的完整扫描。您正在谈论的逻辑 io 大约是表中行数的 4 倍,并且对于不平凡的数据量是可怕的。
  • 仅供参考,“效率不高,但有效”与“有效,但效率不高”相同。我们什么时候放弃了高效作为设计目标?
  • +1 因为当您的数据表的长度不是数百万行时,这是最容易理解的解决方案。当您有多个不同技能水平的开发人员修改代码时,可理解性比不明显的性能更重要。
【解决方案3】:

(T-SQL) 首先获取所有用户及其最大日期。加入表格以查找用户在 maxdates 上的对应值。

create table users (userid int , value int , date datetime)
insert into users values (1, 1, '20010101')
insert into users values (1, 2, '20020101')
insert into users values (2, 1, '20010101')
insert into users values (2, 3, '20030101')

select T1.userid, T1.value, T1.date 
    from users T1,
    (select max(date) as maxdate, userid from users group by userid) T2    
    where T1.userid= T2.userid and T1.date = T2.maxdate

结果:

userid      value       date                                    
----------- ----------- -------------------------- 
2           3           2003-01-01 00:00:00.000
1           2           2002-01-01 00:00:00.000

【讨论】:

    【解决方案4】:

    这将检索 my_date 列值等于该用户 ID 的 my_date 最大值的所有行。这可能会为用户 ID 检索多行,其中最大日期在多行上。

    select userid,
           my_date,
           ...
    from
    (
    select userid,
           my_date,
           ...
           max(my_date) over (partition by userid) max_my_date
    from   users
    )
    where my_date = max_my_date
    

    “分析函数摇滚”

    编辑:关于第一条评论...

    “使用分析查询和自联接违背了分析查询的目的”

    此代码中没有自联接。相反,在包含分析函数的内联视图的结果上放置了一个谓词——这是一个非常不同的问题,并且是完全标准的做法。

    "Oracle中默认窗口是从分区的第一行到当前行"

    windowing 子句仅适用于存在 order by 子句的情况。没有order by子句,默认不应用windowing子句,也不能显式指定。

    代码有效。

    【讨论】:

    • 当应用于具有 880 万行的表时,此查询占用了其他一些投票率高的答案中查询时间的一半。
    • 如果有的话,有人愿意发布一个指向 MySQL 等价物的链接吗?
    • 这不能返回重复项吗?例如。如果两行具有相同的 user_id 和相同的日期(恰好是最大值)。
    • @jastr 我认为这在问题中得到了承认
    【解决方案5】:

    如果 (UserID, Date) 是唯一的,即同一用户没有出现两次日期,则:

    select TheTable.UserID, TheTable.Value
    from TheTable inner join (select UserID, max([Date]) MaxDate
                              from TheTable
                              group by UserID) UserMaxDate
         on TheTable.UserID = UserMaxDate.UserID
            TheTable.[Date] = UserMaxDate.MaxDate;
    

    【讨论】:

    • 我相信你也需要通过UserID加入
    【解决方案6】:

    你应该对之前的查询做这个变体:

    SELECT UserId, Value FROM Users U1 WHERE 
    Date = ( SELECT MAX(Date)    FROM Users where UserId = U1.UserId)
    

    【讨论】:

      【解决方案7】:

      假设 Date 对于给定的 UserID 是唯一的,这里有一些 TSQL:

      SELECT 
          UserTest.UserID, UserTest.Value
      FROM UserTest
      INNER JOIN
      (
          SELECT UserID, MAX(Date) MaxDate
          FROM UserTest
          GROUP BY UserID
      ) Dates
      ON UserTest.UserID = Dates.UserID
      AND UserTest.Date = Dates.MaxDate 
      

      【讨论】:

        【解决方案8】:
        Select  
           UserID,  
           Value,  
           Date  
        From  
           Table,  
           (  
              Select  
                  UserID,  
                  Max(Date) as MDate  
              From  
                  Table  
              Group by  
                  UserID  
            ) as subQuery  
        Where  
           Table.UserID = subQuery.UserID and  
           Table.Date = subQuery.mDate  
        

        【讨论】:

          【解决方案9】:
          select userid, value, date
            from thetable t1 ,
                 ( select t2.userid, max(t2.date) date2 
                     from thetable t2 
                    group by t2.userid ) t3
           where t3.userid t1.userid and
                 t3.date2 = t1.date
          

          恕我直言,这行得通。高温

          【讨论】:

            【解决方案10】:

            我认为这应该可行?

            Select
            T1.UserId,
            (Select Top 1 T2.Value From Table T2 Where T2.UserId = T1.UserId Order By Date Desc) As 'Value'
            From
            Table T1
            Group By
            T1.UserId
            Order By
            T1.UserId
            

            【讨论】:

              【解决方案11】:

              这应该很简单:

              SELECT UserId, Value
              FROM Users u
              WHERE Date = (SELECT MAX(Date) FROM Users WHERE UserID = u.UserID)
              

              【讨论】:

                【解决方案12】:

                首先尝试我误读了这个问题,按照上面的答案,这是一个正确结果的完整示例:

                CREATE TABLE table_name (id int, the_value varchar(2), the_date datetime);
                
                INSERT INTO table_name (id,the_value,the_date) VALUES(1 ,'a','1/1/2000');
                INSERT INTO table_name (id,the_value,the_date) VALUES(1 ,'b','2/2/2002');
                INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'c','1/1/2000');
                INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'d','3/3/2003');
                INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'e','3/3/2003');
                

                --

                  select id, the_value
                      from table_name u1
                      where the_date = (select max(the_date)
                                     from table_name u2
                                     where u1.id = u2.id)
                

                --

                id          the_value
                ----------- ---------
                2           d
                2           e
                1           b
                
                (3 row(s) affected)
                

                【讨论】:

                  【解决方案13】:
                  SELECT userid, MAX(value) KEEP (DENSE_RANK FIRST ORDER BY date DESC)
                    FROM table
                    GROUP BY userid
                  

                  【讨论】:

                  • 在我使用具有大量行的表的测试中,此解决方案所用的时间大约是接受答案中的两倍。
                  • 我确认它比其他解决方案快得多
                  • 问题是它没有返回完整记录
                  • @user2067753 不,它不会返回完整记录。您可以在多个列上使用相同的 MAX()..KEEP.. 表达式,因此您可以选择所需的所有列。但是如果你想要大量的列并且更喜欢使用 SELECT * 会很不方便。
                  【解决方案14】:

                  我知道您要求使用 Oracle,但在 SQL 2005 中我们现在使用它:

                  
                  -- Single Value
                  ;WITH ByDate
                  AS (
                  SELECT UserId, Value, ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY Date DESC) RowNum
                  FROM UserDates
                  )
                  SELECT UserId, Value
                  FROM ByDate
                  WHERE RowNum = 1
                  
                  -- Multiple values where dates match
                  ;WITH ByDate
                  AS (
                  SELECT UserId, Value, RANK() OVER (PARTITION BY UserId ORDER BY Date DESC) Rnk
                  FROM UserDates
                  )
                  SELECT UserId, Value
                  FROM ByDate
                  WHERE Rnk = 1
                  

                  【讨论】:

                    【解决方案15】:

                    我没有 Oracle 对其进行测试,但最有效的解决方案是使用分析查询。它应该看起来像这样:

                    SELECT DISTINCT
                        UserId
                      , MaxValue
                    FROM (
                        SELECT UserId
                          , FIRST (Value) Over (
                              PARTITION BY UserId
                              ORDER BY Date DESC
                            ) MaxValue
                        FROM SomeTable
                      )
                    

                    我怀疑您可以摆脱外部查询并将 distinct 放在内部,但我不确定。与此同时,我知道这个可行。

                    如果您想了解分析查询,我建议您阅读http://www.orafaq.com/node/55http://www.akadia.com/services/ora_analytic_functions.html。这是简短的摘要。

                    在后台,分析查询对整个数据集进行排序,然后按顺序对其进行处理。在处理它时,您根据某些标准对数据集进行分区,然后对于每一行查看某个窗口(默认为当前行的分区中的第一个值 - 该默认值也是最有效的)并且可以使用分析函数的数量(其列表与聚合函数非常相似)。

                    在这种情况下,这是内部查询的作用。整个数据集按 UserId 然后 Date DESC 排序。然后它一次性处理它。对于每一行,您返回 UserId 和为该 UserId 看到的第一个日期(因为日期按 DESC 排序,这是最大日期)。这为您提供了重复行的答案。然后外部 DISTINCT 压缩重复项。

                    这不是一个特别引人注目的分析查询示例。为了获得更大的胜利,请考虑使用一张财务收据表,并为每个用户和收据计算他们支付的总金额。分析查询有效地解决了这个问题。其他解决方案效率较低。这就是为什么它们是 2003 SQL 标准的一部分。 (不幸的是 Postgres 还没有它们。Grrr...)

                    【讨论】:

                    • 您还需要返回日期值才能完整回答问题。如果这意味着另一个 first_value 子句,那么我建议解决方案比它应该的更复杂,并且基于 max(date) 的分析方法读起来更好。
                    • 问题陈述没有说明返回日期。您可以通过添加另一个 FIRST(Date) 或仅通过查询 Date 并将外部查询更改为 GROUP BY 来做到这一点。我会使用第一个并期望优化器一次计算两者。
                    • “问题陈述没有说明返回日期”......是的,你是对的。对不起。但是添加更多的 FIRST_VALUE 子句很快就会变得混乱。这是一个单窗口排序,但如果你有 20 列要为该行返回,那么你已经编写了很多代码来处理。
                    • 我还想到这个解决方案对于单个用户 ID 具有多个具有最大日期和不同值的行的数据是不确定的。问题中的错误多于答案。
                    • 我同意它非常冗长。但是,一般情况下 SQL 不就是这种情况吗?你是对的,解决方案是不确定的。处理关系有多种方法,有时每种方法都是您想要的。
                    【解决方案16】:

                    我看到很多人使用子查询或其他窗口函数来执行此操作,但我经常通过以下方式进行这种不使用子查询的查询。它使用普通的标准 SQL,因此它应该适用于任何品牌的 RDBMS。

                    SELECT t1.*
                    FROM mytable t1
                      LEFT OUTER JOIN mytable t2
                        ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
                    WHERE t2.UserId IS NULL;
                    

                    换句话说:从t1 获取行,其中不存在具有相同UserId 和更大日期的其他行。

                    (我将标识符“日期”放在分隔符中,因为它是 SQL 保留字。)

                    如果是t1."Date" = t2."Date",则出现加倍。通常表有 auto_inc(seq) 键,例如id。 为了避免加倍可以使用如下:

                    SELECT t1.*
                    FROM mytable t1
                      LEFT OUTER JOIN mytable t2
                        ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date") 
                             OR (t1."Date" = t2."Date" AND t1.id < t2.id))
                    WHERE t2.UserId IS NULL;
                    

                    来自@Farhan 的回复:

                    这里有更详细的解释:

                    外部联接尝试将t1t2 联接。默认返回t1的所有结果,如果t2有匹配,也返回。如果在t2 中没有与t1 的给定行匹配,则查询仍返回t1 的行,并使用NULL 作为所有t2 列的占位符。这就是外部联接的一般工作方式。

                    这个查询的技巧是设计连接的匹配条件,使得t2 必须匹配相同 userid更大 date。这个想法是,如果t2 中存在具有更大date 的行,那么与userid 相比,t1 中的行不能是最大的date .但是如果没有匹配项——即如果t2 中不存在大于date 的行大于t1 中的行——我们知道t1 中的行是具有最大date 的行对于给定的userid

                    在这些情况下(不匹配时),t2 的列将是 NULL - 甚至是连接条件中指定的列。这就是我们使用WHERE t2.UserId IS NULL 的原因,因为我们正在搜索给定userid 没有找到更大date 的行的情况。

                    【讨论】:

                    • 哇比尔。这是我见过的这个问题最有创意的解决方案。它在我相当大的数据集上也非常高效。这肯定优于我见过的许多其他解决方案或我自己解决这个难题的尝试。
                    • 当应用于具有 880 万行的表时,此查询花费的时间几乎是接受答案中的两倍。
                    • @Derek:优化取决于 RDBMS 的品牌和版本,以及是否存在适当的索引、数据类型等。
                    • 在 MySQL 上,这种查询似乎实际上导致它循环遍历表之间的笛卡尔连接的结果,导致 O(n^2) 时间。使用子查询方法将查询时间从 2.0s 减少到 0.003s。 YMMV。
                    • 有没有办法调整它以匹配日期是小于或等于用户给定日期的最大日期的行?例如,如果用户给出日期“23-OCT-2011”,并且该表包含“24-OCT-2011”、“22-OCT-2011”、“20-OCT-2011”的行,那么我想得到“2011 年 10 月 22 日”。一直在挠头,读这个sn-p有一段时间了……
                    【解决方案17】:

                    不在工作,我手头没有 Oracle,但我似乎记得 Oracle 允许在 IN 子句中匹配多个列,这至少应该避免使用相关子查询的选项,即很少有好主意。

                    可能是这样的(不记得列列表是否应该加括号):

                    SELECT * 
                    FROM MyTable
                    WHERE (User, Date) IN
                      ( SELECT User, MAX(Date) FROM MyTable GROUP BY User)
                    

                    编辑:刚刚尝试过:

                    SQL> create table MyTable (usr char(1), dt date);
                    SQL> insert into mytable values ('A','01-JAN-2009');
                    SQL> insert into mytable values ('B','01-JAN-2009');
                    SQL> insert into mytable values ('A', '31-DEC-2008');
                    SQL> insert into mytable values ('B', '31-DEC-2008');
                    SQL> select usr, dt from mytable
                      2  where (usr, dt) in 
                      3  ( select usr, max(dt) from mytable group by usr)
                      4  /
                    
                    U DT
                    - ---------
                    A 01-JAN-09
                    B 01-JAN-09
                    

                    所以它可以工作,尽管其他地方提到的一些新奇的东西可能性能更高。

                    【讨论】:

                    • 这也适用于 PostgreSQL。我喜欢它的简单性和通用性——子查询说“这是我的标准”,外部查询说“这是我想看到的细节”。 +1。
                    【解决方案18】:

                    这也将处理重复(为每个 user_id 返回一行):

                    SELECT *
                    FROM (
                      SELECT u.*, FIRST_VALUE(u.rowid) OVER(PARTITION BY u.user_id ORDER BY u.date DESC) AS last_rowid
                      FROM users u
                    ) u2
                    WHERE u2.rowid = u2.last_rowid
                    

                    【讨论】:

                      【解决方案19】:

                      这里的答案只有 Oracle。这是所有 SQL 中更复杂的答案:

                      谁的整体作业成绩最好(作业总分最高)?

                      SELECT FIRST, LAST, SUM(POINTS) AS TOTAL
                      FROM STUDENTS S, RESULTS R
                      WHERE S.SID = R.SID AND R.CAT = 'H'
                      GROUP BY S.SID, FIRST, LAST
                      HAVING SUM(POINTS) >= ALL (SELECT SUM (POINTS)
                      FROM RESULTS
                      WHERE CAT = 'H'
                      GROUP BY SID)
                      

                      还有一个更难的例子,需要一些解释,我没有时间atm:

                      给出 2008 年最流行的书(ISBN 和书名),即 2008 年最常被借阅的书。

                      SELECT X.ISBN, X.title, X.loans
                      FROM (SELECT Book.ISBN, Book.title, count(Loan.dateTimeOut) AS loans
                      FROM CatalogEntry Book
                      LEFT JOIN BookOnShelf Copy
                      ON Book.bookId = Copy.bookId
                      LEFT JOIN (SELECT * FROM Loan WHERE YEAR(Loan.dateTimeOut) = 2008) Loan 
                      ON Copy.copyId = Loan.copyId
                      GROUP BY Book.title) X
                      HAVING loans >= ALL (SELECT count(Loan.dateTimeOut) AS loans
                      FROM CatalogEntry Book
                      LEFT JOIN BookOnShelf Copy
                      ON Book.bookId = Copy.bookId
                      LEFT JOIN (SELECT * FROM Loan WHERE YEAR(Loan.dateTimeOut) = 2008) Loan 
                      ON Copy.copyId = Loan.copyId
                      GROUP BY Book.title);
                      

                      希望这对(任何人)有帮助.. :)

                      问候, 古斯

                      【讨论】:

                      • 接受的答案不是“仅限 Oracle”——它是标准 SQL(许多 DBMS 支持)
                      【解决方案20】:

                      刚刚对此进行了测试,它似乎可以在日志表上工作

                      select ColumnNames, max(DateColumn) from log  group by ColumnNames order by 1 desc
                      

                      【讨论】:

                        【解决方案21】:

                        只需要在工作中写一个“活”的例子:)

                        这个支持同一日期的多个 UserId 值。

                        列: 用户 ID、值、日期

                        SELECT
                           DISTINCT UserId,
                           MAX(Date) OVER (PARTITION BY UserId ORDER BY Date DESC),
                           MAX(Values) OVER (PARTITION BY UserId ORDER BY Date DESC)
                        FROM
                        (
                           SELECT UserId, Date, SUM(Value) As Values
                           FROM <<table_name>>
                           GROUP BY UserId, Date
                        )
                        

                        您可以使用 FIRST_VALUE 代替 MAX 并在解释计划中查找。我没有时间玩它。

                        当然,如果搜索巨大的表,最好在查询中使用 FULL 提示。

                        【讨论】:

                          【解决方案22】:

                          难道不是 QUALIFY 子句既简单又最好?

                          select userid, my_date, ...
                          from users
                          qualify rank() over (partition by userid order by my_date desc) = 1
                          

                          就上下文而言,在 Teradata 上,此 QUALIFY 版本在 17 秒内运行,在 23 秒内运行“内联视图”/Aldridge 解决方案 #1。

                          【讨论】:

                          • 这是我认为的最佳答案。但是,在存在平局的情况下,请小心使用 rank() 函数。您最终可能会得到多个rank=1。如果您真的只希望返回一条记录,最好使用row_number()
                          • 另外,请注意 QUALIFY 子句特定于 Teradata。在 Oracle 中(至少),您必须在包装 select 语句上使用 WHERE 子句嵌套查询和过滤器(我想这可能会影响性能)。
                          【解决方案23】:

                          对于 PostgreSQL 8.4 或更高版本,您可以这样使用:

                          select user_id, user_value_1, user_value_2
                            from (select user_id, user_value_1, user_value_2, row_number()
                                    over (partition by user_id order by user_date desc) 
                                  from users) as r
                            where r.row_number=1
                          

                          【讨论】:

                            【解决方案24】:
                            select VALUE from TABLE1 where TIME = 
                               (select max(TIME) from TABLE1 where DATE= 
                               (select max(DATE) from TABLE1 where CRITERIA=CRITERIA))
                            

                            【讨论】:

                              【解决方案25】:
                              select   UserId,max(Date) over (partition by UserId) value from users;
                              

                              【讨论】:

                              • 这将返回所有行,而不仅仅是每个用户一行。
                              【解决方案26】:

                              没有分区 KEEP、DENSE_RANK 概念的 MySQL 解决方案。

                              select userid,
                                     my_date,
                                     ...
                              from
                              (
                              select @sno:= case when @pid<>userid then 0
                                                  else @sno+1
                                  end as serialnumber, 
                                  @pid:=userid,
                                     my_Date,
                                     ...
                              from   users order by userid, my_date
                              ) a
                              where a.serialnumber=0
                              

                              参考:http://benincampus.blogspot.com/2013/08/select-rows-which-have-maxmin-value-in.html

                              【讨论】:

                              • 这在“其他数据库上也”不起作用。这仅适用于 MySQL,也可能适用于 SQL Server,因为它具有类似的变量概念。它绝对不适用于 Oracle、Postgres、DB2、Derby、H2、HSQLDB、Vertica、Greenplum。此外,接受的答案是标准的 ANSI SQL(只知道 MySQL 不支持)
                              • 马,我猜你是对的。我不了解其他数据库或 ANSI。我的解决方案能够解决 MySQL 中的问题,它没有适当支持 ANSI SQL 以标准方式解决它。
                              【解决方案27】:

                              我迟到了,但以下 hack 将优于相关子查询和任何分析函数,但有一个限制:值必须转换为字符串。所以它适用于日期、数字和其他字符串。代码看起来不太好,但执行配置文件很棒。

                              select
                                  userid,
                                  to_number(substr(max(to_char(date,'yyyymmdd') || to_char(value)), 9)) as value,
                                  max(date) as date
                              from 
                                  users
                              group by
                                  userid
                              

                              这段代码之所以这么好用,是因为它只需要扫描表一次。它不需要任何索引,最重要的是它不需要对表进行排序,而大多数分析功能都需要这样做。如果您需要过滤单个用户 ID 的结果,索引会有所帮助。

                              【讨论】:

                              • 与大多数执行计划相比,这是一个很好的执行计划,但是将所有这些技巧应用于更多的领域会很乏味,并且可能会适得其反。但非常有趣 - 谢谢。见sqlfiddle.com/#!4/2749b5/23
                              • 你是对的,它可能会变得乏味,这就是为什么只有在查询性能需要时才应该这样做。 ETL 脚本通常就是这种情况。
                              • 这很好。使用 LISTAGG 做了类似的事情,但看起来很难看。 postgres 使用 array_agg 有更好的选择。看我的回答:)
                              【解决方案28】:

                              如果你使用 Postgres,你可以使用 array_agg 喜欢

                              SELECT userid,MAX(adate),(array_agg(value ORDER BY adate DESC))[1] as value
                              FROM YOURTABLE
                              GROUP BY userid
                              

                              我不熟悉 Oracle。这就是我想出来的

                              SELECT 
                                userid,
                                MAX(adate),
                                SUBSTR(
                                  (LISTAGG(value, ',') WITHIN GROUP (ORDER BY adate DESC)),
                                  0,
                                  INSTR((LISTAGG(value, ',') WITHIN GROUP (ORDER BY adate DESC)), ',')-1
                                ) as value 
                              FROM YOURTABLE
                              GROUP BY userid 
                              

                              两个查询都返回与接受的答案相同的结果。请参阅 SQLFiddles:

                              1. Accepted answer
                              2. My solution with Postgres
                              3. My solution with Oracle

                              【讨论】:

                              • 谢谢。很高兴知道array-agg 函数。假设,array-agg 可能不适用于每个userid(按列分组)有太多行的情况?而且,当我们在结果中需要多个选择列时;然后,我们需要将array_agg 应用于所有其他列,即使用adate 与其他所有选择列执行group by?不过,对于 OP 的问题,答案很好!
                              【解决方案29】:

                              检查this link,如果您的问题与该页面相似,那么我建议您使用以下查询,该查询将为该链接提供解决方案

                              select distinct sno,item_name,max(start_date) over(partition by sno),max(end_date) over(partition by sno),max(creation_date) over(partition by sno), max(last_modified_date) over(partition by sno) from uniq_select_records order by sno,item_name asc;

                              将给出与该链接相关的准确结果

                              【讨论】:

                                【解决方案30】:

                                Oracle 12c+ 中,您可以使用 Top n 查询以及分析函数 rank 来非常简洁地实现此目的,无需子查询:

                                select *
                                from your_table
                                order by rank() over (partition by user_id order by my_date desc)
                                fetch first 1 row with ties;
                                

                                上面返回每个用户最大 my_date 的所有行。

                                如果您只想要一行具有最大日期,请将rank 替换为row_number

                                select *
                                from your_table
                                order by row_number() over (partition by user_id order by my_date desc)
                                fetch first 1 row with ties; 
                                

                                【讨论】:

                                  猜你喜欢
                                  • 2010-10-09
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2014-12-21
                                  • 1970-01-01
                                  • 2018-10-14
                                  相关资源
                                  最近更新 更多