【问题标题】:Sampling from Oracle, Need exact number of results (Sample Clause)从 Oracle 抽样,需要确切数量的结果(样本子句)
【发布时间】:2013-04-08 03:09:27
【问题描述】:

我正在尝试从 Peoplesoft 数据库中随机抽取人口样本。在线搜索使我认为 select 语句的 Sample 子句可能是我们使用的可行选项,但是我无法理解 Sample 子句如何确定返回的样本数。我查看了此处的 oracle 文档: http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10002.htm#i2065953

但上面的参考资料只讨论了用于创建示例的语法。我提出问题的原因是我需要了解样本百分比如何确定返回的样本量。似乎它将随机数应用于您要求的百分比,然后使用种子数来计算每“n”条记录。我们的要求是我们抽取准确数量的样本,例如,它们是随机选择的,并且它们代表整个表格(或者至少是我们使用过滤器选择的数据分组)

在 10200 个项目的总体中,如果我需要大约 100 个项目的样本,我可以使用以下语句:

SELECT * FROM PS_LEDGER SAMPLE(1) --1 % of my total population
WHERE DEPTID = '700064' 

但是,我们需要提取准确数量的样本(在本例中为 100),因此我可以选择一个几乎总是返回大于我需要的数量的样本大小,然后在 IE 中对其进行修剪

SELECT Count(*) FROM PS_LEDGER SAMPLE(2.5) --this percent must always give > 100 items
WHERE DEPTID = '700064' and rownum < 101

我担心这样做是因为我的样本不能统一代表整个人口。例如,如果示例函数在创建自己的随机生成的种子后仅提取每 N 条记录,则选择 rownum

【问题讨论】:

  • 如果没有order byrownum 并没有真正意义上的“表底”概念。在应用rownum 过滤器(在外部select 中)之前,您可以通过dbms_random.value 明确订购您的样本,如果它是一个小表,您可能根本不需要样本?
  • “代表”是什么意思?通常,没有 order by 子句的查询结果集中记录的顺序是任意的。但是,您可以通过使用dbms_random 对其进行排序来明确随机化它。例如:select * from ps_ledger where deptid ='7000064' order by dbms_random.value.

标签: oracle sample random-sample


【解决方案1】:

我一直在摆弄一个类似的问题。首先,我设置了不同 Stratum 的样本量。在你的情况下,它只有一个。 ('700064')。所以在 with 子句或临时表中我这样做了:

Select DEPTID, Count(*) SAMPLE_ONE 
FROM PS_LEDGER  Sample(1)
WHERE DEPTID = '700064' 
Group By DEPTID

这会告诉您预期的 1% 样本中的记录。让我们称之为 TABLE_1

然后我这样做了:

Select 
Ceil (Rank() over (Partition by DEPTID Order by DBMS_RANDOM.VALUE)
            / (Select SAMPLE_ONE From TABLE_1) STRATUM_GROUP
,A.*
FROM PS_LEDGER 

再做一张桌子。那么你得到的是大约随机样本集。 1% 的大小。

因此,如果您的原始表包含 1000 条记录,您将获得 100 个随机样本集,每个样本集包含 10 个项目。

然后您可以随机选择其中一项进行测试。

不确定我是否已经很好地解释了这一点,但它对我有用。我在一张拥有超过 1000 万条记录的桌子上设置了 168 个 Stratum,效果非常好。

如果您需要更多解释或可以改进这一点,请不要犹豫。

问候

【讨论】:

    【解决方案2】:

    借用 jonearles 的示例表,我看到完全相同的东西(在 OEL 开发人员图像上的 11gR2 中),通常得到 a 的值严重偏向 1;对于小样本量,我有时根本看不到任何东西。通过我在评论中提到的额外随机化/限制步骤:

    select a, count(*) from (
        select * from test1 sample (1)
        order by dbms_random.value
    )
    where rownum < 101
    group by a;
    

    ...我跑了三遍:

             A   COUNT(*)
    ---------- ----------
             1         71
             2         29
    
             A   COUNT(*)
    ---------- ----------
             1        100
    
             A   COUNT(*)
    ---------- ----------
             1         64
             2         36
    

    是的,100% 真的在第二次运行时以1 的身份返回。倾斜本身似乎是相当随机的。我尝试使用 block 修饰符,这似乎没什么区别,也许令人惊讶 - 我可能认为在这种情况下它会变得更糟。

    这可能会更慢,尤其是对于小样本量,因为它必须覆盖整个表格;但确实给了我相当一致的分裂:

    select a, count(*) from (
        select a, b from (
            select a, b, row_number() over (order by dbms_random.value) as rn
            from test1
        )
        where rn < 101
    )
    group by a;
    

    我跑了 3 次:

             A   COUNT(*)
    ---------- ----------
             1         48
             2         52
    
             A   COUNT(*)
    ---------- ----------
             1         57
             2         43
    
             A   COUNT(*)
    ---------- ----------
             1         49
             2         51
    

    ...看起来更健康一些。当然是 YMMV。


    This Oracle article 涵盖了一些抽样技术,您可能还想评估ora_hash 方法以及分层版本(如果您的数据传播和您对“代表性”的要求需要它)。

    【讨论】:

      【解决方案3】:

      您不能相信SAMPLE 从表中返回一组真正随机的行。该算法似乎是基于表格的物理特性。

      create table test1(a number, b char(2000));
      
      --Insert 10K fat records.  A is always 1.
      insert into test1 select 1, level from dual connect by level <= 10000;
      
      --Insert 10K skinny records.  A is always 2.
      insert into test1 select 2, null from dual connect by level <= 10000;
      
      --Select about 10 rows.
      select * from test1 sample (0.1) order by a;
      

      多次运行最后一个查询,您几乎不会看到任何 2。如果您按字节而不是按行进行测量,这可能是一个准确的样本。

      这是一个偏斜数据的极端例子,但我认为这足以表明RANDOM 没有按照手册所暗示的方式工作。正如其他人所建议的那样,您可能想要ORDER BY DBMS_RANDOM.VALUE

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-08
        • 2021-05-15
        相关资源
        最近更新 更多