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

时间:2014-05-29 12:19:30

标签: sql sql-server random

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

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

因此,如果英国客户占客户表中记录的15%,那么在100k样本集中必须有15k英国客户,然后每个市场都有相同的数据。

有办法做到这一点吗?

2 个答案:

答案 0 :(得分:5)

首先,一个简单的随机样本在表示市场规模时应该做得很好。你所要求的是一个分层的样本。

获得此类样本的一种方法是随机排序数据并在每个组中分配序号。然后将序列号标准化为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名,你将得到前五个值,这是一个分层样本。

答案 1 :(得分:1)

正如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。