【问题标题】:How to retrieve half of records from a table - Oracle 11g如何从表中检索一半的记录 - Oracle 11g
【发布时间】:2015-06-11 13:19:31
【问题描述】:

我怎样才能从一个表中检索(select)一半的记录,例如,一个有 1000 行的表,从表中检索 500 (50%) 条记录。 (在这种情况下,我可以使用 rownum,因为我们知道行的确切数量(1000) - select * from table where rownum <= 500),但我必须计算每个表才能实现语句。

你认为我能做到这一点的最佳方法是什么?

【问题讨论】:

  • dba_tables 上有一个 num_rows 列,但我认为只有在分析表时才会刷新
  • 您使用的是什么版本的 Oracle?而且,“一半”需要精确到什么程度?
  • Oracle 11g,可能是随机的

标签: sql oracle


【解决方案1】:

好吧,你可以数行并选择一半:

select *
from   my_table
where  rownum <= (select count(*)/2 from my_table)

这将倾向于选择物理段中连续的行。

或者……

select *
from   (select rownum rn, * from my_table)
where  mod(rn,2) = 0

这将倾向于选择“每隔一个”行,因此您可以从物理数据段中获得相当均匀的分布。

或者……

select *
from   my_table sample (50)

这大约是行数的一半。

或者……

select *
from   my_table sample block (50)

这将是段高水位线以下大约一半数据块中的行。

可能有很多不同的方法可用,你想要哪一种可能取决于你是否想要伪随机选择。

如果您想使用查询的输出,请使用以下内容:

select ...
from   (select *
        from   my_table
        where  rownum <= (select count(*)/2 from my_table)) my_table
join   ...

在这种情况下,SAMPLE 语法会更紧凑。

【讨论】:

  • 赞成 sample 语法,如果“大约一半”对 OP 来说足够的话,这将是正确的解决方案。
  • 我用过select * from mytable where rownum &lt;= (select count(*)/2 form mytable),但如果我只是咨询一张桌子就可以了,如果必须咨询3张桌子呢?
【解决方案2】:

如果您使用的是 Oracle 12c,则可以使用 Top-n 行限制 功能,该功能允许限制 行百分比

例如,在我的SCOTT 架构中的EMP 表中,我有14 rows,我希望首先根据sal 的顺序50 percent rows

SQL> SELECT empno, sal FROM emp
  2  ORDER BY sal
  3  FETCH FIRST 50 PERCENT ROWS ONLY;

     EMPNO        SAL
---------- ----------
      7369        800
      7900        950
      7876       1100
      7521       1250
      7654       1250
      7934       1300
      7844       1500

7 rows selected.

SQL>

【讨论】:

    【解决方案3】:

    带有NTILE窗口功能:

    select * from (SELECT *, NTILE(2) OVER(ORDER BY (SELECT NULL FROM DUAL)) nt FROM TableName) as t
    where nt = 1
    

    或:

    select * from (SELECT *, NTILE(2) OVER(ORDER BY NULL) nt FROM TableName) as t
    where nt = 1
    

    【讨论】:

    • SELECT NULL 我认为您的语法不正确。
    • @LalitKumarB,好的,谢谢。我记得在 Sql Server oredring by NULL 直接会导致错误。在 oracle 中它正在工作。
    • 不需要select语句,ORDER BY NULL就够了。
    【解决方案4】:

    据我所知,执行此操作的最佳方法是执行以下代码块:

    SELECT * FROM 表名
    WHERE ROWNUM

    并获得下半场:

    选择 * 来自
    (SELECT ROWNUM AS RN,table_name.* FROM table_name)
    WHERE RN > (SELECT COUNT(*)/2 FROM table_name);

    【讨论】:

      【解决方案5】:

      你想要哪一半的行?

      每隔一行...

      Select * from table t
      Where Mod(rownum, 2) = 0
      

      这是上半场...

      Select * from table t
      Where rownum <= 
          (Select count(*) 
           from table) / 2
      

      【讨论】:

      • 第一个查询肯定有语法错误。我猜这是sql server语法。在 Oracle 中它肯定会失败。
      • “修改”以使其符合 Oracle 语法
      • 出于好奇,为什么需要一半的行?
      • 一种可能性,确定中位数。
      【解决方案6】:

      如果记录总数不是偶数,则上述查询将不起作用,这里是工作查询,无论count(*)/2 返回整数还是小数

      SELECT ROWNUM, tmp.* 
      FROM employees tmp
      WHERE TO_NUMBER(ROWNUM) <= (SELECT count(*)/2 FROM employees);
      

      【讨论】:

        猜你喜欢
        • 2013-07-13
        • 1970-01-01
        • 1970-01-01
        • 2012-04-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-01
        • 2019-05-05
        相关资源
        最近更新 更多