Hive中collect_list()排序问题详解

简介: 笔记

来看一道互联网公司的面试题:

有个用户好友表:字段如下
uid  fans_uid   score
返回:uid, fans_uid_list【fans_uid的拼接串,按照score降序拼接】

给出数据源:每个uid,有很多对应的fans_uid,每个fans_uid 都对应一个score,我们需要按uid分组,将fans_uid 的score按降序排序,将fans_uid 放在一个列表中,做好友推荐

create temporary table tb_user_fans as 
select 1 as uid,'a' as fans_uid,3 as score
union all
select 1 as uid,'b' as fans_uid,1 as score
union all
select 1 as uid,'c' as fans_uid,4 as score
union all
select 1 as uid,'d' as fans_uid,3 as score
union all
select 1 as uid,'e' as fans_uid,2 as score
union all
select 2 as uid,'a' as fans_uid,4 as score
union all
select 2 as uid,'b' as fans_uid,3 as score
union all
select 2 as uid,'c' as fans_uid,1 as score
union all
select 2 as uid,'d' as fans_uid,2 as score
union all
select 2 as uid,'e' as fans_uid,5 as score
union all
select 3 as uid,'a' as fans_uid,6 as score
union all
select 3 as uid,'b' as fans_uid,3 as score
union all
select 3 as uid,'c' as fans_uid,5 as score
;

我想要的结果:按照uid分组,按照score降序排序,取出fans_uid放到列表里

1 [c,d,a,e,b]
2 [e,a,b,d,c]
3 [a,c,b]

解法一:

select
    uid,
    collect_list(fans_uid) as fans_uid_list
from (
select 
    uid
    ,fans_uid
    ,score
    ,row_cnt
from (
    select
        uid
        ,fans_uid
        ,score
        ,row_number() over (partition by uid order by score desc ) as row_cnt
    from tb_user_fans
    ) 
order by row_cnt asc
)
group by uid
order by uid

如果数据量大不推荐使用,因为使用到了全局排序order by,只有一个reducer,那么数据量大计算要很长时间。

解法二:

select 
    uid
    ,regexp_replace(
        concat_ws(
            ','
            ,sort_array(
                collect_list(
                    conact_ws(':' ,lpad(cast(rank_num as string),5,'0') ,fans_uid)
                )
            )
        )
        ,'\\d+\:'
        ,''
    ) as fans_uid_list
from (
    select
        uid
        ,fans_uid
        ,score
        ,row_number() over (partition by uid order by score desc ) as row_cnt
    from tb_user_fans
)
group by uid

这里将row_cnt放在了fans_uid之前,用冒号分隔,然后用sort_array函数对collect_list之后的结果进行排序(只支持升序)。特别注意,rank必须要在高位补足够的0对齐,因为排序的是字符串而不是数字,如果不补0的话,按字典序排序就会变成1, 10, 11, 12, 13, 2, 3, 4…,又不对了。

将排序的结果拼起来之后,用regexp_replace函数替换掉冒号及其前面的数字,大功告成。


解法三:最优解,写法简洁

select
    uid,
    collect_list(fans_uid) as fans_uid_list
from (
  select 
      uid
      ,fans_uid
      ,score
  from tb_user_fans distribute by uid sort by uid,score desc 
)
group by uid

诀窍是使用带有DISTRIBUTE BY和SORT BY语句的子查询

相关文章
|
1月前
|
前端开发 JavaScript UED
React 拖拽排序组件 Draggable List
在现代Web应用中,拖拽排序功能显著提升用户体验。使用React结合`react-dnd`库,可以轻松创建高效且易于维护的拖拽排序组件。通过简单的拖拽操作,用户能直观调整列表项顺序,适用于任务管理、看板工具等场景。实现步骤包括项目初始化、安装依赖、创建基础组件、添加拖拽功能及管理状态和事件。常见问题如拖拽效果不流畅、顺序未更新等可通过性能优化、正确处理索引交换等方式解决。移动端支持也需考虑,确保跨平台的良好体验。
103 25
|
3月前
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
62 0
|
5月前
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
36 3
|
6月前
|
存储 Java API
【Java高手必备】揭秘!如何优雅地对List进行排序?掌握这几种技巧,让你的代码瞬间高大上!
【8月更文挑战第23天】本文深入探讨了Java中对List集合进行排序的各种方法,包括使用Collections.sort()、自定义Comparator以及Java 8的Stream API。通过示例代码展示了不同情况下如何选择合适的方法:从简单的整数排序到自定义类对象的排序,再到利用Comparator指定特殊排序规则,最后介绍了Stream API在排序操作中的简洁应用。理解这些技术的区别与应用场景有助于提高编程效率。
212 4
|
6月前
|
缓存 容器
从一个文件中讲稿未知数目的整数。对这些整数排序,然后把它们输出到标准输出设备。选用vector、deque 还是 list?
从文件读取未知数量的整数,排序后输出。选用`std::vector`因其能高效读取大量数据至连续内存,直接使用内置排序,提升缓存效率。避免使用`std::deque`和`std::list`,前者内存管理开销大,后者排序及随机访问较慢。
61 14
|
7月前
|
Java API 存储
Java如何对List进行排序?
【7月更文挑战第26天】
324 9
Java如何对List进行排序?
|
9月前
|
SQL 存储 大数据
Hive的查询、数据加载和交换、聚合、排序、优化
Hive的查询、数据加载和交换、聚合、排序、优化
187 2
|
9月前
|
SQL 数据处理 HIVE
【Hive】写出Hive中split、coalesce及collect_list函数的用法?
【4月更文挑战第17天】【Hive】写出Hive中split、coalesce及collect_list函数的用法?
|
9月前
|
搜索推荐 算法 C++
list容器-排序案例讲解
list容器-排序案例讲解
53 0
|
9月前
|
算法 C++ 容器
list容器-反转和排序讲解39
list容器-反转和排序讲解39
97 0