MySql:不均匀分布的数据上均匀分布的样本量
MySql: Evenly distributed sample size on unevenly distributed data
假设我有 10.000 个预订客户资料。
这些配置文件具有以下变量:
- 持续时间(假期天数)
- 目的地(也许是巴西)
- People_amount(多少个一起去)
- 起飞(他们想离开的日期)
我想通过预订引擎传递其中的 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
这个想法是,出现次数少的值将获得较低的排序值,因此会更频繁地出现在结果集的开头,以补偿它们的低频率。
假设我有 10.000 个预订客户资料。 这些配置文件具有以下变量:
- 持续时间(假期天数)
- 目的地(也许是巴西)
- People_amount(多少个一起去)
- 起飞(他们想离开的日期)
我想通过预订引擎传递其中的 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
这个想法是,出现次数少的值将获得较低的排序值,因此会更频繁地出现在结果集的开头,以补偿它们的低频率。