表:
UserId, Value, Date.
我想获得UserId,为每个UserId的最大值(日期)的值。也就是说,具有最新日期的每个UserId的值。有没有一种方法可以在SQL中简单地做到这一点?(最好是Oracle)
更新:为任何歧义道歉:我需要得到所有的用户id。但是对于每个UserId,只有该用户拥有最新日期的行。
表:
UserId, Value, Date.
我想获得UserId,为每个UserId的最大值(日期)的值。也就是说,具有最新日期的每个UserId的值。有没有一种方法可以在SQL中简单地做到这一点?(最好是Oracle)
更新:为任何歧义道歉:我需要得到所有的用户id。但是对于每个UserId,只有该用户拥有最新日期的行。
当前回答
我已经很晚了,但下面的黑客将超越相关子查询和任何分析功能,但有一个限制:值必须转换为字符串。所以它适用于日期,数字和其他字符串。代码看起来不太好,但执行配置文件很棒。
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过滤结果,索引将有所帮助。
其他回答
在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
由于不工作,我手头没有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
所以它是有效的,尽管其他地方提到的一些新东西可能性能更好。
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
这将检索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的默认窗口是从分区的第一行到当前一行
加窗条款仅适用于存在按顺序条款的情况。如果没有按子句排序,默认情况下就不会应用任何窗口子句,也不能显式地指定任何窗口子句。
代码可以工作。
使用代码:
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;