sql - 获取具有最大值的行的最有效方法是什么?

标签 sql oracle greatest-n-per-group

想象一下我们有一家漂亮的酒店。这家酒店的数据库只有一张表:

room check-in    check_out   other columns...
1    2020-02-04  2020-02-05  ...
1    2020-02-06  2020-02-09  ...
1    2020-04-20  NULL        ...
2    2020-03-29  2020-04-01  ...
2    2020-04-17  2020-04-18  ...

使用其他列的值为每个房间选择最后一次入住的最佳和有效方法是什么(否则我只会使用 room, max(check-in)

预期结果是

room check_in   check_out  other columns... 
1    2020-04-20 NULL       ...
2    2020-04-17 2020-04-18 ...

我想到的第一个想法是将这个表与其副本连接起来:

WITH last_checkins AS (
    SELECT room, max(check_in) AS last_c
    FROM rooms
    GROUP BY room
)
SELECT *
FROM rooms r
         INNER JOIN last_chekins c
                    ON r.room = c.room
                        AND r.checkin = c.last_c;

我不喜欢这个想法的地方

  • 这似乎有点低效。这家酒店拥有3000万间客房。所以我必须加入两张大 table
  • 我有点害怕参加约会。感觉好像有什么事情可能出问题了。顺便说一句,Check_in 列也有时间。这使得事情变得更加困惑。

我想知道我的担忧是否相关?

最佳答案

最方便的可能是row_number():

select r.*
from (select r.*,
             row_number() over (partition by room order by checkin dec) as seqnum
      from rooms r
     ) r
where seqnum = 1;

有了(房间, checkin )上的索引,这也应该具有良好的性能。

有时相关子查询效果更好:

select r.*
from rooms r
where r.checkin = (select max(r2.checkin)
                   from rooms r2
                   where r2.room = r.room
                  );

Oracle 有一个很好的优化器,所以我不确定哪个更适合您的情况。

关于sql - 获取具有最大值的行的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61325573/

相关文章:

SQL命令顺序

java - 多端口Weblogic

sql - 如何在 Oracle SQL 查询中修剪前缀字符串?

mysql - 如何分配虚拟自增等级限制为4?

mysql - 在sql中按组排序

mysql - 计入查询破坏预期结果

sql - BigQuery - 连接谓词中不支持带表的子查询

mysql - PostgreSQL - 创建 View 时需要帮助

Oracle 数据脱敏

sql - 合并多个表中的最新条目