如何在Oracle SQL中选择前1和按日期排序?

How to select top 1 and ordered by date in Oracle SQL?

本问题已经有最佳答案,请猛点这里访问。

有一个明确的答案:如何选择前1名:

1
SELECT * FROM TABLE_NAME WHERE rownum = 1

以及如何按日期降序排序:

1
SELECT * FROM TABLE_NAME ORDER BY trans_date DESC

但它们不协同工作(rownum不是根据trans_date生成的):

1
... WHERE rownum = 1 ORDER BY trans_date DESC

问题是如何选择按日期排序的前1个?


1
... WHERE rownum = 1 ORDER BY trans_date DESC

这将选择任意选择的一条记录(where rownum = 1),然后对这一条记录(order by trans_date desc进行排序。

如Ivan所示,您可以使用子查询来排序记录,然后在外部查询中使用where rownum = 1保存第一条记录。但是,这是非常特定于Oracle的,并且违反了SQL标准,其中子查询结果被认为是无序的(即,DBMS可以忽略ORDER BY子句)。

所以最好用标准溶液。从Oracle 12c开始:

1
2
3
4
SELECT *
FROM TABLE_NAME
ORDER BY trans_date DESC
fetch FIRST 1 ROW ONLY;

在旧版本中:

1
2
3
4
5
6
7
SELECT *
FROM
(
  SELECT t.*, ROW_NUMBER() OVER (ORDER BY trans_date DESC) AS rn
  FROM TABLE_NAME t
)
WHERE rn = 1;

现代甲骨文版本有FETCH FIRST

1
2
SELECT * FROM TABLE_NAME ORDER BY trans_date DESC
fetch FIRST 1 ROW ONLY


您可以使用窗口函数:

1
2
3
4
5
6
7
8
9
SELECT t.*
FROM (
  SELECT *,
         MIN(trans_date) OVER () AS min_date,
         MAX(trans_date) OVER () AS max_date
  FROM the_table
) t
WHERE trans_date = min_date
   OR trans_date = max_date;

另一个选项是在派生表上联接

1
2
3
4
5
6
7
8
SELECT t1.*
FROM the_table
  JOIN (
    SELECT MIN(trans_date) OVER () AS min_date,
           MAX(trans_date) OVER () AS max_date
    FROM the_table
) t2 ON t1.trans_date = t2.min_date
     OR t1.trans_date = t2.max_date;

不确定哪一个更快,您需要检查执行计划


应该有子查询,以便组合rownum & order可以工作:

1
SELECT * FROM (SELECT * FROM TABLE_NAME ORDER BY trans_date DESC) AS tb WHERE rownum = 1