选择 n 个随机行,其中 n 与每个值占总人口的百分比成比例

Posted

技术标签:

【中文标题】选择 n 个随机行,其中 n 与每个值占总人口的百分比成比例【英文标题】:Select n amount of random rows where n is proportionate to each value's % of total population 【发布时间】:2014-07-18 22:46:56 【问题描述】:

我有一张包含 5800 万条客户记录的表格。每个客户都有一个市场价值(EN、US、FR 等)

我正在尝试选择一个包含来自每个市场的客户的 100k 样本集。样本中每个市场的客户比率必须与实际表格中的比率相匹配。

因此,如果英国客户占客户表中记录的 15%,则 100k 样本集中必须有 15k 英国客户,并且每个市场的英国客户都相同。

有没有办法做到这一点?

【问题讨论】:

【参考方案1】:

首先,一个简单的随机样本应该可以很好地代表市场规模。您要求的是分层样本。

获取此类样本的一种方法是对数据进行随机排序,并在每组中分配一个序号。然后将序号归一化到 0 到 1 之间,最后按归一化值排序,选择前“n”行:

select top 100000 c.*
from (select c.*,
             row_number() over (partition by market order by rand(checksum(newid()))
                               ) as seqnum,
             count(*) over (partition by market) as cnt
      from customers c
     ) c
order by cast(seqnum as float) / cnt

如果您查看数据,可能会清楚发生了什么。考虑从以下位置抽取 5 个样本:

1    A
2    B
3    C
4    D
5    D
6    D
7    B
8    A
9    D
10   C

第一步在每个市场中随机分配一个序号:

1    A      1
2    B      1
3    C      1
4    D      1
5    D      2
6    D      3
7    B      2
8    A      2   
9    D      4
10   C      2

接下来,标准化这些值:

1    A      1      0.50
2    B      1      0.50
3    C      1      0.50
4    D      1      0.25
5    D      2      0.50
6    D      3      0.75
7    B      2      1.00
8    A      2      1.00
9    D      4      1.00
10   C      2      1.00

现在,如果您取前 5 个值,您将得到前五个值,这是一个分层样本。

【讨论】:

我已经尝试过您的查询,似乎newid() 附近有错误。 end 有必要吗?因为在 SQL Server 2008 上,它会将其标记为错误(以及之后的 ))。【参考方案2】:

正如 Gordon Linoff 所指出的,使用随机抽取的大样本将为您提供一个与原始总体具有良好统计近似的样本。

要强制总体和样本之间的百分比相等,您可以计算并使用所有需要的参数:总体维度和分区维度,并添加随机 ID。

Declare @sampleSize INT
Set @sampleSize = 100000

With D AS (
  SELECT customerID
       , Country
       , Count(customerID) OVER (PARTITION BY Null) TotalData
       , Count(customerID) OVER (PARTITION BY Country) CountryData
       , Row_Number() OVER (PARTITION BY Country 
                            ORDER BY rand(checksum(newid()))) ID
  FROM   customer
)
SELECT customerID
     , Country
FROM   D
WHERE  ID <= Round((Cast(CountryData as Float) / TotalData) * @sampleSize, 0)
ORDER BY Country

SQLFiddle demo 数据较少。

请注意,WHERE 条件中函数的近似值会使返回的数据比所需数据少一点或多一点,例如在演示中,返回的行数是 9 而不是 10。

【讨论】:

以上是关于选择 n 个随机行,其中 n 与每个值占总人口的百分比成比例的主要内容,如果未能解决你的问题,请参考以下文章

如何使用纯 SQL 选择 N 个随机行?

将一个表中的单行连接到另一个表中的 n 个随机行

Hibernate Criteria API:获取 n 个随机行

sql [sql]从每个类别中选择1个随机行

MySQL 从 600K 行中快速选择 10 个随机行

VBA/宏根据多个条件复制随机行