ChatGPT解决这个技术问题 Extra ChatGPT

我如何在 Oracle 中获得前 1 名? [复制]

这个问题在这里已经有了答案:如何在排序后限制 Oracle 查询返回的行数? (14 个回答) 6 个月前关闭。

如何执行以下操作?

select top 1 Fname from MyTbl

Oracle 11g

你能告诉我们你想要“前1名”的顺序吗?
首先,您永远不应该依赖数据库引擎来做到这一点。如果您想知道类似的事情,请放入音序器。当您这样做时,可以保证它们将按照插入的顺序编号。
关于这个主题的非常有用的材料 use-the-index-luke.com/sql/partial-results/top-n-queries

P
Peter Mortensen

如果您只想要第一个选定的行,您可以:

select fname from MyTbl where rownum = 1

您还可以使用分析函数对前 x 进行排序和取值:

select max(fname) over (rank() order by some_factor) from MyTbl

如果您只想要 1 行并且不在乎哪一行,这很好。如果您想要特定的行,例如最近的记录,则需要在子选择中进行排序,例如 Vash 的答案。 Oracle 在排序之前分配 rownums。
@斯科特是的。那是对的。和帕特里克,好点我认为语法不正确。它真的应该是一个保留(dense_rank()最后......)
第一个示例和第二个示例的区别在于,第一个示例选择了 A 行(任意行,没有顺序)。第二个示例获取第一行的值,而不执行顺序内部查询(如下例所示)。
语法不正确: select max(fname) over (rank() order by some_factor) from MyTbl
@Sepster,我同意不应该避免它,只是根据我的经验,我没有遇到很多知道这个功能的人
D
Damian Leszczyński - Vash
SELECT *
  FROM (SELECT * FROM MyTbl ORDER BY Fname )
 WHERE ROWNUM = 1;

这个答案正确地获得了 TOP 行(在限制 ROWNUM 之前对结果进行排序)。
这个答案不是精确的翻译——原始查询没有 ORDER BY,也没有返回表中的所有列。
我的立场是正确的(见下文)。时间到了就会换票。
@OMGPonis 是的。但这可能是大多数人真正想要的,他们通过谷歌搜索他们的问题来访问这个页面
这肯定是这个线程中的获胜答案。我可能会添加一条注释,对于 top X,可以将其更改为 WHERE ROWNUM <= X
P
Peter Mortensen

使用 Oracle 12c(2013 年 6 月),您可以像下面这样使用它。

SELECT * FROM   MYTABLE
--ORDER BY COLUMNNAME -OPTIONAL          
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY

有趣的命令,我在这里使用的是 12c,而 OFFSET 0 ROWS 显然不是必需的,您可以使用 FETCH NEXT 1 ROWS ONLY 甚至 FETCH FIRST ROW ONLY,顺序很重要,否则它将等同于仅使用 WHERE rownum = 1。我什至在 OUTER APPLY 指令中尝试过它,它的工作方式类似于 Ms-SQL 的 TOP 函数。
你是对的@RafaelMerlin。在您的帖子之后,我认识到不需要 OFFSET 0 ROWS。这在检索 top X 和 top Y 之间的数据时会很有用。
到目前为止一切顺利,但有一个重要的缺失点是 TIES。请参阅 this,了解版本 12c +12c - 出现关联的情况
S
Sarath Subramanian

您可以在子查询中将 ROW_NUMBER()ORDER BY 子句一起使用,并使用此列代替 TOP N。这可以逐步解释。

请参阅下表,其中包含两列 NAMEDT_CREATED

https://i.stack.imgur.com/a8AS1.jpg

如果您只需要获取前两个日期而不考虑 NAME,则可以使用以下查询。逻辑已经写在查询里面

-- The number of records can be specified in WHERE clause
SELECT RNO,NAME,DT_CREATED
FROM
(
    -- Generates numbers in a column in sequence in the order of date
    SELECT ROW_NUMBER() OVER (ORDER BY DT_CREATED) AS RNO,
    NAME,DT_CREATED
    FROM DEMOTOP
)TAB
WHERE RNO<3;

结果

https://i.stack.imgur.com/f7Yfl.jpg

在某些情况下,我们需要为每个 NAME 选择 TOP N 结果。在这种情况下,我们可以在子查询中使用带有 ORDER BY 子句的 PARTITION BY。请参阅以下查询。

-- The number of records can be specified in WHERE clause
SELECT RNO,NAME,DT_CREATED
FROM
(
  --Generates numbers in a column in sequence in the order of date for each NAME
    SELECT ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY DT_CREATED) AS RNO,
    NAME,DT_CREATED
    FROM DEMOTOP
)TAB
WHERE RNO<3;

结果

https://i.stack.imgur.com/o203n.jpg


使用 ROW_NUMBER()... 是比主题答案更正确的解决方案。此解决方案(以及 max(field) 变体)的一个问题是您无法执行“select ... (select ROW_NUMBER() ... ) for update;”之类的操作。
它有时在 PL/SQL 中非常重要(抱歉,在 5 分钟限制内无法编辑之前的评论)。
在这种情况下,我们可以在外部使用 CTE。正确的? @Alexo 宝。
我想我不明白你。 for update 子句可以在 ROWID 被 Oracle“轻松”保留时使用。因此分组(以及由于使用分析子句而分组)隐藏了真实的 ROWID 并且无法锁定行。其次,CTE(with (select ... ) as 子句)对这个问题没有任何改变,CTE 只是为了阅读和支持查询。正确的? @萨拉特·阿瓦纳武
请注意我自己。 ROWID 的问题实际上是由于 RNO<3 条件而发生的,在这种情况下,RNO 的值与 ROWID 没有连接,这就是 Oracle 无法锁定行的原因。
V
ViRuSTriNiTy
select * from (
    select FName from MyTbl
)
where rownum <= 1;

S
Sunil

你可以做类似的事情

    SELECT *
      FROM (SELECT Fname FROM MyTbl ORDER BY Fname )
 WHERE rownum = 1;

您也可以使用分析函数 RANK 和/或 DENSE_RANK,但 ROWNUM 可能是最简单的。


你能帮忙举一些排名等的例子吗?
查询不起作用。
O
OMG Ponies

利用:

SELECT x.*
  FROM (SELECT fname 
          FROM MyTbl) x
 WHERE ROWNUM = 1

如果使用 Oracle9i+,您可以查看 using analytic functions like ROW_NUMBER() but they won't perform as well as ROWNUM


不错的答案,但包含一个小错字。你说Oracle9i+不应该是8i吗? download-west.oracle.com/docs/cd/A87860_01/doc/server.817/…
@carpenteri:确实,8i 中提供了分析功能——不记得细节了,但直到 9i 版本才真正向公众提供分析功能。
小评论 - Vash 下面的答案包括内部查询的 ORDER BY,如果您想要 fname 的 TOP 值而不是“第一”(可以是任何东西,很可能是插入的第一行),这很关键。可能值得编辑?
@JulesLt:OP 提供的查询不包括 ORDER BY,因此这是答案代表和对 Oracle 语法的精确翻译。
我对 SQL SERVER TOP 语法的误解(错误地认为它类似于 RANK 中的 FIRST,而不是 ROWNUM)。投票赞成。
P
Peter Mortensen

从表中选择第一行和从表中选择一行是两个不同的任务,需要不同的查询。有很多可能的方法可以做到这一点。其中四个是:

第一的

select  max(Fname) from MyTbl;

第二

select  min(Fname) from MyTbl;

第三

select  Fname from MyTbl  where rownum = 1;

第四

select  max(Fname) from MyTbl where rowid=(select  max(rowid) from MyTbl)

C
Caius Jard

我有同样的问题,我可以用这个解决方案解决这个问题:

select a.*, rownum 
from (select Fname from MyTbl order by Fname DESC) a
where
rownum = 1

您可以在将第一个值放在首位之前对结果进行排序。

祝你好运