使用 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 选择随机行的主要内容,如果未能解决你的问题,请参考以下文章

如何在 hive sql 中获取每个组的最大 row_number()

如何测试蜂巢中的数字条件?

hive - 如何为每个匹配选择前 N 个元素

SQL Case中的多个条件

SQL / Hive 选择具有特定列值的第一行

Sql 查询为表中的每个组合返回一条记录