【问题标题】:How to Select Top 100 rows in Oracle?如何在 Oracle 中选择前 100 行?
【发布时间】:2015-01-18 00:26:31
【问题描述】:

我的要求是获取每个客户的最新订单,然后获取前100条记录。

我写了一个如下查询来获取每个客户的最新订单。内部查询工作正常。但我不知道如何根据结果获得前 100 个。

    SELECT * FROM (
      SELECT id, client_id, ROW_NUMBER() OVER(PARTITION BY client_id ORDER BY create_time DESC) rn 
      FROM order
    ) WHERE rn=1

有什么想法吗?谢谢。

【问题讨论】:

  • 澄清一下 - 您想要每个客户的前 100 个,还是前 100 个客户?
  • 我想要前 100 个客户的最新订单。

标签: sql oracle


【解决方案1】:

假设 create_time 包含订单创建的时间,并且您希望 100 个客户拥有最新订单,您可以:

  • 在最里面的查询中添加 create_time
  • create_time desc 对外部查询的结果进行排序
  • 添加一个最外层查询,使用ROWNUM过滤前100行

查询:

  SELECT * FROM (
     SELECT * FROM (
        SELECT 
          id, 
          client_id, 
          create_time,
          ROW_NUMBER() OVER(PARTITION BY client_id ORDER BY create_time DESC) rn 
        FROM order
      ) 
      WHERE rn=1
      ORDER BY create_time desc
  ) WHERE rownum <= 100

Oracle 12c 更新

在 12.1 版中,Oracle 引入了"real" Top-N queries。使用新的FETCH FIRST... 语法,您还可以使用:

  SELECT * FROM (
    SELECT 
      id, 
      client_id, 
      create_time,
      ROW_NUMBER() OVER(PARTITION BY client_id ORDER BY create_time DESC) rn 
    FROM order
  ) 
  WHERE rn = 1
  ORDER BY create_time desc
  FETCH FIRST 100 ROWS ONLY)

【讨论】:

  • 实际上我很困惑,如果我不在我的第一个查询之上放置另一个 SELECT,而是在 rn=1 旁边写 ROWNUM
  • SELECT * FROM ( SELECT id, client_id, create_time, ROW_NUMBER() OVER(PARTITION BY client_id ORDER BY create_time DESC) rn FROM order ) WHERE rn=1 AND rownum&lt;=100 ORDER BY create_time desc
  • 因为在这种情况下,您不会按 create_time 对行进行排序 - 您的结果集是随机排序的,您只需获取前 100 个;这本质上是一个随机样本。
  • 它只是随机获得前 100 个 rn=1 的订单,对吧?
  • 伙计们... 12.1 版本太糟糕了,之前的版本太离谱了! Oracle 的人没有看到这在 SQL Server、MySQL 和 PostGreSQL 中是多么容易吗?
【解决方案2】:

你应该在 oracle 中使用 rownum 来做你想做的事

where rownum <= 100

另请参阅那些对您有帮助的答案

limit in oracle

select top in oracle

select top in oracle 2

【讨论】:

  • 这个有两种方法。SELECT * FROM(SELECT * FROM ( SELECT id, client_id, ROW_NUMBER() OVER(PARTITION BY client_id ORDER BY create_time DESC) rn FROM order ) WHERE rn=1) WHERE ROWNUM &lt; 101或者SELECT * FROM ( SELECT id, client_id, ROW_NUMBER() OVER(PARTITION BY client_id ORDER BY create_time DESC) rn FROM order ) WHERE rn=1 AND ROWNUM&lt;101这两个我测试了,结果不一样。
【解决方案3】:

正如 Moneer Kamal 所说,您可以简单地做到这一点:

SELECT id, client_id FROM order 
WHERE rownum <= 100
ORDER BY create_time DESC;

请注意,在获得第 100 行之后完成了排序。这可能对不想订购的人有用。

更新:

要将 order byrownum 一起使用,您必须编写如下内容:

SELECT * from (SELECT id, client_id FROM order ORDER BY create_time DESC) WHERE rownum <= 100;

【讨论】:

    【解决方案4】:

    前 10 个客户插入 db(表客户):

    select * from customers where customer_id <=
    (select  min(customer_id)+10 from customers)
    
    Last 10 customers inserted into db (table customers):
    
    select * from customers where customer_id >=
    (select  max(customer_id)-10 from customers)
    

    希望这会有所帮助....

    【讨论】:

    • 您的查询假定 customer_id 中没有间隙。如果这个假设是错误的(因为行被删除,因为用于填充 PK 的序列使用缓存/增量大于 1 / ...),它将返回比请求的更少的行。
    【解决方案5】:

    选择最近更新的前 n 行

    SELECT * 
    FROM (
       SELECT * 
       FROM table 
       ORDER BY UpdateDateTime DESC
    )
    WHERE ROWNUM < 101;
    

    【讨论】:

      【解决方案6】:

      试试这个:

         SELECT *
      FROM (SELECT * FROM (
          SELECT 
            id, 
            client_id, 
            create_time,
            ROW_NUMBER() OVER(PARTITION BY client_id ORDER BY create_time DESC) rn 
          FROM order
        ) 
        WHERE rn=1
        ORDER BY create_time desc) alias_name
      WHERE rownum <= 100
      ORDER BY rownum;
      

      或顶部:

      SELECT TOP 2 * FROM Customers; //But not supported in Oracle
      

      注意:我想您的内部查询没问题。请分享您的输出。

      【讨论】:

      • 它给出了类似“ORA-00923: FROM keyword not found where expected”的错误。我认为 TOP 行不通。
      • Oracle 不支持 TOP
      • 抱歉,我的系统中还没有安装 oracle,它是基本的 SQL 命令,这就是我要求输出的原因
      • 已编辑为 oracle 尝试此操作
      猜你喜欢
      • 1970-01-01
      • 2013-12-22
      • 2014-01-06
      • 2021-09-30
      • 1970-01-01
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多