MySql:不均匀分布的数据上均匀分布的样本量

MySql: Evenly distributed sample size on unevenly distributed data

假设我有 10.000 个预订客户资料。 这些配置文件具有以下变量:

我想通过预订引擎传递其中的 1.000 (10%) 个进行定价,但要开发独立的洞察分析,我必须(尽可能多地)均匀分布配置文件的特征。例如。如果所有配置文件都有 3 种 People_amount(1、2 和 3),最终我想在 33,33% 的 10% 内选择 People_amount = 1、33, 33% People_amount = 2 和 33,33% People_amount = 3.

但是...

因为配置文件集分布不均匀(例如所有配置文件的 70% 由 People_amount = 1 组成)我不知道如何 find/create 一种循环(或其他东西)由该特征内的所有品种填充 SELECT 直到 1 耗尽并与其余的一起走得更远。

也许是关于我想如何填充我的 10k 个人资料的 10% 样本的示例:

Profile_id  People_amount                                     Profile_id  People_amount
1           1                                                           1           1
2           1                                                           5           2
3           1                                                           8           3
4           1       --> Filling the sample by even distribution         2           1
5           2       of available profile characteristics                6           2
6           2                                                           9           3   
7           2                                                           3           1
8           3                                                           7           2
9           3                                                           4           1

希望能帮到你!

您可以使用 union 来限制每个子 select:

(SELECT * FROM profiles WHERE People_amount=1 LIMIT 333)
UNION
(SELECT * FROM profiles WHERE People_amount=2 LIMIT 333)
UNION
(SELECT * FROM profiles WHERE People_amount=3 LIMIT 333)

需要括号才能将 LIMIT 应用于每个子 select。

更动态的方法

如果不知道people_amount的可能取值个数,则上述方法不可行。然后我会提出一个查询,其中 ORDER BY 子句根据出现次数分配 people_amount 值。它不会给出完全相等的分布,但不同的值将在结果集中具有可比较的存在:

select     p.*
from       (
            select   people_amount,  
                     count(*) as occurrences
            from     profiles
            group by people_amount) as stats
inner join profiles p
        on p.people_amount = stats.people_amount         
order by   rand() * stats.occurrences
limit      1000

SQL fiddle(如果没有超载)。

如果您想将其扩展到其他列,例如 Destination,您可以按如下方式进行:

select     p.*
from       (
            select   people_amount,  
                     destination,
                     count(*) as occurrences
            from     profiles
            group by people_amount,
                     destination) as stats
inner join profiles p
        on p.people_amount = stats.people_amount         
       and p.destination = stats.destination
order by   rand() * stats.occurrences
limit      1000

这个想法是,出现次数少的值将获得较低的排序值,因此会更频繁地出现在结果集的开头,以补偿它们的低频率。