使用 sql (Hive) 中的条件为每个 ID 选择随机行
Posted
技术标签:
【中文标题】使用 sql (Hive) 中的条件为每个 ID 选择随机行【英文标题】:select random rows for each ID with a condition in sql (Hive) 【发布时间】:2019-11-14 16:36:25 【问题描述】:下面是一个有 85M 行的表,其中 ~7M 不同的 product_ids。日期范围为 2019 年 1 月 1 日至 2019 年 10 月 31 日(共 10 个月)。
product_id status date
60151028 LESS 2019-04-04
86069378 MORE 2019-08-12
99660145 LESS 2019-01-06
16775944 LESS 2019-05-12
52801157 LESS 2019-09-06
4493185 LESS 2019-09-13
39917883 LESS 2019-07-03
87716367 MORE 2019-05-24
90785856 MORE 2019-05-15
15412972 SAME 2019-07-11
12236638 SAME 2019-03-23
.
.
.
.
60151028 LESS 2019-10-12
我想为我的分析生成一个随机样本,并且我想为每个 ID 和状态选择 4 个随机行——例如,我想要:
-
4 行,ID 为 60151028,status = "LESS"
4 行,ID 为 60151028,status = "MORE"
4 行 ID 为 60151028,状态 =“SAME”,所有产品 ID 都类似,这意味着有 12 行产品 ID 相同。
应在这 10 个月内的所有日期中随机选择数据。下面是结果视图:
product_id status date
60151028 LESS 2019-04-04
60151028 LESS 2019-07-18
60151028 LESS 2019-09-23
60151028 LESS 2019-01-25
60151028 SAME 2019-05-14
60151028 SAME 2019-10-11
60151028 SAME 2019-03-31
60151028 SAME 2019-08-30
60151028 MORE 2019-04-27
60151028 MORE 2019-09-19
60151028 MORE 2019-10-29
60151028 MORE 2019-06-04
.
.
.
39917883 SAME 2019-08-03
39917883 SAME 2019-02-26
39917883 SAME 2019-10-07
.
.
.
我一直在考虑以下查询(Hive),但我无法想到如何随机选择状态 =“LESS”或“MORE”等的行。任何帮助将不胜感激!!
另外,我知道有一个 rand() 函数是 hive sql 但我不知道如何在这里使用它。
select max(case when status = 'LESS' then 1 else 0 end) OVER (PARTITION by product_id) as flg
,detail1.*
from
(
select row_number() OVER
(partition by product_id order by date) as rn
from db.table
) detail1
UNION ALL
select max(case when status = 'SAME' then 1 else 0 end) OVER (PARTITION by product_id) as flg
,detail2.*
from
(
select row_number() OVER
(partition by product_id order by date) as rn
from db.table
) detail2
UNION ALL
select max(case when status = 'MORE' then 1 else 0 end) OVER (PARTITION by product_id) as flg
,detail3.*
from
(
select row_number() OVER
(partition by product_id order by date) as rn
from db.table
) detail3
【问题讨论】:
【参考方案1】:使用partition by
:
select t.*
from (select t.*
row_number() OVER (partition by product_id, status order by rand()) as seqnum
from db.table
) t
where seqnum <= 4;
编辑:
获取所有状态至少有 4 行的示例:
select t.*
from (select t.*
row_number() OVER (partition by product_id, status order by rand()) as seqnum,
max(ps_cnt) over (partition by product_id) as max_ps_cnt
from (select t.*, count(*) over (partition by product_id, status) as ps_cnt
from db.table t
) t
) t
where seqnum <= 4 and max_ps_cnt >= 4;
【讨论】:
您好,谢谢。结果如下: ``` product_id status date seq_num 100011169 MORE 2019-10-16 1 100011169 MORE 2019-07-29 2 100011169 MORE 2019-07-22 3 100011169 MORE 2019-08-27 4 10001158 01 1 100011855 LESS 2019-01-02 2 100011855 LESS 2019-01-13 3 100011855 LESS 2019-01-04 4 ``` 您的结果是每个 product_id 只给出一个状态。但是,我想要 100011169 4 of MORE、4 of LESS 和 4 of SAME。所以每个产品 id 应该有 12 行,有 4 行 status = 'MORE'.. 等等。 @vineet 。 . .此代码应为数据中的每个产品/状态组合提供四行。您确定您正在运行此查询吗? 嗨,戈登!我的错误,是的,它为每个产品状态组合分配了 4 行。非常感谢,我真的很感激。我刚刚发现有许多 product_id 在 10 个月的范围内只有一种状态。有没有办法只显示所有 3 种状态在这 10 个月范围内至少出现 4 次的 product_Id? 另外,如果可能的话,有没有办法为每个状态获得准确的 4 行(而不是至少 4 行)? @vineet 。 . .你真的应该问一个新问题。但是,仅对具有“足够”行的产品进行抽样符合您提出的问题的精神,因此我编辑了答案。以上是关于使用 sql (Hive) 中的条件为每个 ID 选择随机行的主要内容,如果未能解决你的问题,请参考以下文章