对于另一列的每个非重复值,提取具有列的最大值的行

Fetch the rows which have the Max value for a column for each distinct value of another column

提问人:Umang 提问时间:9/23/2008 最后编辑:philipxyUmang 更新时间:5/13/2023 访问量:685325

问:

桌子:

UserId, Value, Date.

我想获取 UserId,每个 UserId 的 max(Date) 值。也就是说,具有最新日期的每个 UserId 的值。

如何在 SQL 中执行此操作?(最好是 Oracle。

我需要获取所有UserId。但对于每个 UserId,只有该用户具有最新日期的那一行。

SQL Oracle 每个组 Greatest-n-Each Group

评论

26赞 David Aldridge 9/24/2008
如果有多行具有特定用户 ID 的最大日期值,该怎么办?
0赞 vamosrafa 6/20/2013
表格的关键字段是什么?
0赞 Adrian Maxwell 8/7/2014
下面比较了一些解决方案: sqlfiddle.com/#!4/6d4e81/1
1赞 Pacerier 2/3/2015
@DavidAldridge,该列可能是唯一的。
0赞 zloctb 10/11/2015
stackoverflow.com/questions/2854257/......

答:

2赞 jdmichal 9/23/2008 #1

我想是这样的。(请原谅我的任何语法错误;在这一点上,我已经习惯使用HQL!

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

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

评论

0赞 David Aldridge 9/23/2008
不满足“for each UserId”条件
0赞 jdmichal 9/23/2008
它会在哪里失败?对于“用户”中的每个用户 ID,将保证至少返回一行包含该用户 ID。还是我在某个地方遗漏了特例?
59赞 Steve K 9/23/2008 #2

我不知道你的确切列名,但它是这样的:

SELECT userid, value
FROM users u1
WHERE date = (
    SELECT MAX(date)
    FROM users u2
    WHERE u1.userid = u2.userid
)

评论

5赞 David Aldridge 9/23/2008
可能不是很有效,史蒂夫。
7赞 Rafał Dowgird 9/23/2008
您可能低估了 Oracle 查询优化器。
3赞 David Aldridge 9/23/2008
一点也不。几乎可以肯定的是,这将实现为具有嵌套循环连接以获取日期的完全扫描。你说的是逻辑 io,大约是表中行数的 4 倍,对于非平凡的数据量来说是可怕的。
6赞 David Aldridge 9/23/2008
仅供参考,“效率不高,但有效”与“有效但效率不高”相同。我们什么时候放弃了将高效作为设计目标?
11赞 n00b 4/25/2013
+1 因为当您的数据表长度不是数百万行时,这是最容易理解的解决方案。当您有多个不同技能水平的开发人员修改代码时,可理解性比不值得注意的性能的几分之一秒更重要。
1赞 boes 9/23/2008 #3

(T-SQL)首先获取所有用户及其 maxdate。与表联接以查找 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
457赞 4 revs, 3 users 96%David Aldridge #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 中的默认窗口是从分区中的第一行到当前行”

窗口子句仅在存在 order by 子句的情况下适用。如果没有 order by 子句,则默认情况下不应用任何窗口子句,也不能显式指定任何子句。

代码有效。

评论

50赞 Derek Mahar 4/16/2011
当应用于具有 880 万行的表时,此查询所花费的时间是其他一些高投票答案中查询时间的一半。
5赞 redolent 1/10/2015
如果有人愿意发布一个指向MySQL的链接,如果有的话?
3赞 jastr 6/16/2016
这个返回不能重复吗?例如。如果两行具有相同的user_id和相同的日期(恰好是最大值)。
3赞 David Aldridge 6/17/2016
@jastr我认为这个问题已经承认了这一点
9赞 MT0 6/27/2016
您还可以使用(对于每组前 n 名)或(对于每组最大的 n)。MAX(...) OVER (...)ROW_NUMBER() OVER (...)RANK() OVER (...)
-1赞 finnw 9/23/2008 #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;

评论

0赞 Tom H 9/23/2008
我相信您也需要通过UserID加入
2赞 stefano m 9/23/2008 #6

我 Thing you shuold 将这个变体添加到之前的查询中:

SELECT UserId, Value FROM Users U1 WHERE 
Date = ( SELECT MAX(Date)    FROM Users where UserId = U1.UserId)
1赞 marc 9/23/2008 #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 
2赞 Aheho 9/23/2008 #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  
0赞 Zsolt Botykai 9/23/2008 #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

恕我直言,这有效。HTH型

0赞 GateKiller 9/23/2008 #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
0赞 Valerion 9/23/2008 #11

这应该像以下几点一样简单:

SELECT UserId, Value
FROM Users u
WHERE Date = (SELECT MAX(Date) FROM Users WHERE UserID = u.UserID)
0赞 KyleLanser 9/23/2008 #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)
170赞 Dave Costa 9/23/2008 #13
SELECT userid, MAX(value) KEEP (DENSE_RANK FIRST ORDER BY date DESC)
  FROM table
  GROUP BY userid

评论

5赞 Derek Mahar 4/16/2011
在我使用具有大量行的表的测试中,该解决方案花费的时间大约是接受答案中的两倍。
0赞 tamersalama 9/12/2012
我确认它比其他解决方案快得多
5赞 Adrian Maxwell 8/7/2014
麻烦的是它没有返回完整的记录
0赞 Dave Costa 8/8/2014
@user2067753 否,它不会返回完整记录。您可以使用相同的 MAX()..保持。。表达式,因此您可以选择所需的所有列。但是,如果您想要大量列并且更喜欢使用 SELECT *,则很不方便。
15赞 mancaus 9/23/2008 #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
8赞 user11318 9/23/2008 #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 的第一个 Date(因为日期按 DESC 排序,因此这是最大日期)。这为您提供了重复行的答案。然后外部 DISTINCT 压缩重复项。

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

评论

0赞 David Aldridge 9/24/2008
您还需要返回日期值才能完整回答问题。如果这意味着另一个first_value子句,那么我建议解决方案比它应该的更复杂,并且基于 max(date) 的分析方法读起来更好。
0赞 user11318 9/24/2008
问题陈述没有提到返回日期。为此,您可以添加另一个 FIRST(Date),或者只需查询 Date 并将外部查询更改为 GROUP BY。我会使用第一个,并希望优化器在一次传递中计算两者。
0赞 David Aldridge 9/24/2008
“问题陈述没有提到返回日期”......是的,你是对的。不好意思。但是添加更多的FIRST_VALUE条款很快就会变得混乱。这是一个单一窗口排序,但如果你有 20 列要返回该行,那么你就编写了很多代码来涉足。
0赞 David Aldridge 9/24/2008
我还想到,对于单个用户 ID 具有具有最大日期和不同 VALUE 的多行的数据,此解决方案是不确定的。不过,问题中的错误比答案更重要。
1赞 user11318 9/24/2008
我同意这是令人痛苦的冗长。但是,SQL通常不是这样吗?你是对的,解决方案是不确定的。处理关系的方法有很多种,有时每种方法都是你想要的。
514赞 Bill Karwin 9/24/2008 #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;

换言之:从不存在其他行且具有相同且更大日期的行中获取该行。t1UserId

(我将标识符“Date”放在分隔符中,因为它是 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的回复评论:

以下是更详细的说明:

外部连接尝试与 连接。默认情况下,返回 的所有结果,如果 中存在匹配项,则也会返回。如果给定的行 中没有匹配项,则查询仍返回 的行,并用作所有列的占位符。这就是外部连接的一般工作方式。t1t2t1t2t2t1t1NULLt2

此查询的诀窍是设计连接的匹配条件,使其必须匹配相同的更大的 .这个想法是,如果其中存在一行具有更大的 ,那么与之比较的行就不可能是最大的。但是,如果没有匹配项,即如果 中不存在大于 in 的行,我们知道 in 中的行是给定的 的最大行。t2useriddatet2datet1dateuseridt2datet1t1dateuserid

在这些情况下(当没有匹配项时),列将是 -- 甚至是联接条件中指定的列。所以这就是我们使用 ,因为我们正在寻找没有找到给定行且更大的行的情况。t2NULLWHERE t2.UserId IS NULLdateuserid

评论

15赞 Justin Noel 1/13/2011
哇,比尔。这是我见过的解决这个问题的最有创意的解决方案。在我相当大的数据集上,它的性能也相当高。这肯定胜过我见过的许多其他解决方案或我自己解决这个难题的尝试。
44赞 Derek Mahar 4/16/2011
当应用于具有 880 万行的表时,此查询花费的时间几乎是已接受答案中的两倍。
20赞 Bill Karwin 4/20/2011
@Derek:优化取决于 RDBMS 的品牌和版本,以及是否存在适当的索引、数据类型等。
12赞 Jesse 2/22/2012
在MySQL上,这种查询似乎实际上会导致它循环表之间的笛卡尔连接结果,从而导致O(n^2)时间。相反,使用子查询方法将查询时间从 2.0 秒减少到 0.003 秒。YMMV。
2赞 Bill Karwin 9/8/2015
@frank,因为 t2.UserId 在计算外部联接之前不为 null。请研究外部连接。
45赞 Mike Woodhouse 9/24/2008 #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

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

评论

7赞 j_random_hacker 6/15/2010
这在PostgreSQL上也很好用。我喜欢它的简单性和通用性——子查询说“这是我的标准”,外部查询说“这是我想要看到的细节”。+1.
0赞 na43251 2/25/2010 #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
1赞 Guus 4/29/2010 #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)

还有一个更困难的例子,需要一些解释,我没有时间自动取款机:

给出 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);

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

问候 古斯

评论

0赞 12/7/2014
公认的答案不是“仅限 Oracle”——它是标准 SQL(许多 DBMS 都支持)
0赞 Mauro 5/2/2010 #20

刚刚测试过这个,它似乎可以在日志记录表上运行

select ColumnNames, max(DateColumn) from log  group by ColumnNames order by 1 desc
4赞 Truper 6/29/2010 #21

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

此支持在同一日期为 UserId 提供多个值。

列: UserId、值、日期

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 提示。

7赞 wcw 10/20/2011 #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运行。

评论

1赞 cartbeforehorse 5/26/2012
在我看来,这是最好的答案。但是,在有联系的情况下要小心该功能。你最终可能会得到不止一个.如果您确实只想返回一条记录,最好使用。rank()rank=1row_number()
3赞 cartbeforehorse 5/26/2012
此外,请注意,该子句特定于 Teradata。在 Oracle(至少)中,您必须在包装 select 语句上使用子句嵌套查询和过滤(我想这可能会影响性能)。QUALIFYWHERE
7赞 Cito 11/1/2011 #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

评论

2赞 Ciro Santilli OurBigBook.com 6/29/2022
对于PostgreSQL,我们现在可以使用它完美地解决了用例:stackoverflow.com/questions/586781/...DISTINCT ON
2赞 nouky 11/23/2011 #24
select VALUE from TABLE1 where TIME = 
   (select max(TIME) from TABLE1 where DATE= 
   (select max(DATE) from TABLE1 where CRITERIA=CRITERIA))
-1赞 王奕然 4/21/2013 #25
select   UserId,max(Date) over (partition by UserId) value from users;

评论

3赞 Jon Heller 4/21/2013
这将返回所有行,而不仅仅是每个用户一行。
1赞 Ben Lin 8/31/2013 #26

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

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

评论

0赞 8/31/2013
这“在其他数据库上也不起作用”。这仅适用于 MySQL,可能适用于 SQL Server,因为它具有类似的变量概念。它绝对不能在 Oracle、Postgres、DB2、Derby、H2、HSQLDB、Vertica、Greenplum 上运行。此外,公认的答案是标准的ANSI SQL(只知道MySQL不支持)
0赞 Ben Lin 9/6/2013
马,我想你是对的。我不了解其他数据库或 ANSI。我的解决方案能够解决MySQL中的问题,MySQL没有对ANSI SQL的适当支持,无法以标准方式解决它。
4赞 aLevelOfIndirection 7/21/2014 #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 的结果,索引将有所帮助。

评论

0赞 Adrian Maxwell 8/7/2014
与大多数计划相比,这是一个很好的执行计划,但将所有这些技巧应用于多个领域将是乏味的,并且可能会与之背道而驰。但非常有趣 - 谢谢。查看 sqlfiddle.com/#!4/2749b5/23
0赞 aLevelOfIndirection 8/13/2014
你是对的,它可能会变得乏味,这就是为什么只有在查询的性能需要它时才应该这样做。ETL 脚本通常就是这种情况。
0赞 Bruno Calza 11/13/2014
这很好。使用 LISTAGG 做了类似的事情,但看起来很丑。Postgres 具有更好的 altenative 使用 array_agg。查看我的答案:)
3赞 Bruno Calza 11/12/2014 #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. 接受的答案
  2. 我的Postgres解决方案
  3. 我的 Oracle 解决方案

评论

0赞 Binita Bharati 9/10/2021
谢谢。很高兴了解该功能。假设,对于每个行数过多(按列分组)的情况可能效果不佳?而且,当我们在结果中需要多个选择列时;然后,我们需要应用于其他每一列,即对每隔一列选择列执行一个?不过,OP的问题回答得很好!array-aggarray-agguseridarray_agggroup byadate
-1赞 Smart003 6/17/2015 #29

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

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;

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

7赞 Gurwinder Singh 3/26/2017 #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 的所有行。

如果只想有一行包含最大日期,则将 替换为:rankrow_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; 
-1赞 Natty 5/11/2017 #31

使用代码:

select T.UserId,T.dt from (select UserId,max(dt) 
over (partition by UserId) as dt from t_users)T where T.dt=dt;

这将检索结果,而不考虑 UserId 的重复值。 如果你的 UserId 是唯一的,那么它就会变得更加简单:

select UserId,max(dt) from t_users group by UserId;
-2赞 praveen 9/8/2017 #32
SELECT a.* 
FROM user a INNER JOIN (SELECT userid,Max(date) AS date12 FROM user1 GROUP BY userid) b  
ON a.date=b.date12 AND a.userid=b.userid ORDER BY a.userid;
4赞 markusk 10/31/2017 #33

使用 ROW_NUMBER() 为每个 分配一个唯一的降序排名,然后过滤到每个 的第一行(即 = 1)。DateUserIdUserIdROW_NUMBER

SELECT UserId, Value, Date
FROM (SELECT UserId, Value, Date,
        ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY Date DESC) rn
      FROM users) u
WHERE rn = 1;
-1赞 praveen 10/16/2018 #34
SELECT a.userid,a.values1,b.mm 
FROM table_name a,(SELECT userid,Max(date1)AS mm FROM table_name GROUP BY userid) b
WHERE a.userid=b.userid AND a.DATE1=b.mm;

评论

0赞 einverne 10/16/2018
虽然这可能会回答作者的问题,但它缺少一些解释性词语和文档链接。如果没有一些短语,原始代码片段就不是很有帮助。您可能还会发现如何写出一个好的答案非常有帮助。请编辑您的答案。
-1赞 2 revs, 2 users 60%kiruba #35

下面的查询可以工作:

SELECT user_id, value, date , row_number() OVER (PARTITION BY user_id ORDER BY date desc) AS rn
FROM table_name
WHERE rn= 1