5

我正在尝试从 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 < 101 将切断从表底部选择的所有记录。我正在寻找的是一种从表中准确提取 100 条记录的方法,这些记录是随机选择的,并且相当代表整个表。请帮忙!!

4

3 回答 3

6

借用 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

1是的,100% 真的像第二轮一样回来了。倾斜本身似乎是相当随机的。我尝试使用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;

通过三轮我得到:

         A   COUNT(*)
---------- ----------
         1         48
         2         52

         A   COUNT(*)
---------- ----------
         1         57
         2         43

         A   COUNT(*)
---------- ----------
         1         49
         2         51

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


这篇 Oracle 文章介绍了一些抽样技术,如果您的数据传播和您对“代表性”的要求需要它,您可能还想评估该ora_hash方法以及分层版本。

于 2013-04-16T06:48:10.710 回答
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.

于 2013-04-16T05:13:12.440 回答
0

我一直在摆弄一个类似的问题。首先,我设置了不同 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,效果非常好。

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

问候

于 2015-12-17T15:19:20.140 回答