表:

UserId, Value, Date.

我想获得UserId,为每个UserId的最大值(日期)的值。也就是说,具有最新日期的每个UserId的值。有没有一种方法可以在SQL中简单地做到这一点?(最好是Oracle)

更新:为任何歧义道歉:我需要得到所有的用户id。但是对于每个UserId,只有该用户拥有最新日期的行。


当前回答

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;

其他回答

如果(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;

这也会处理重复的数据(为每个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

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

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

我没有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/55和http://www.akadia.com/services/ora_analytic_functions.html。这是一个简短的总结。

在底层,分析查询对整个数据集进行排序,然后按顺序进行处理。当你处理它的时候,你根据特定的标准对数据集进行分区,然后对每一行查看一些窗口(默认为当前行分区中的第一个值-默认也是最有效的),并可以使用许多分析函数(其列表非常类似于聚合函数)计算值。

在本例中,下面是内部查询的功能。整个数据集先按UserId排序,再按Date DESC排序,然后一次处理。对于每一行,您返回UserId和该UserId看到的第一个日期(因为日期是按DESC排序的,所以这是最大日期)。这就得到了重复行的答案。然后外部的DISTINCT压缩重复项。

这并不是一个特别引人注目的分析查询示例。如果想获得更大的胜利,可以考虑制作一张财务收据表格,计算每个用户和收据的总花费。分析查询可以有效地解决这个问题。其他解决方案效率较低。这就是为什么它们是2003 SQL标准的一部分。(不幸的是Postgres还没有。叽阿…)

答案是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);

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

问候 古斯