如何通过蜂巢中的collect_set()操作使用订单

vka*_*l11 2 sql hive

在表1中,我有customer_id,item_id和item_rank(根据某些销售情况的项目等级)。我想为每个customer_id收集项目列表,并根据item_rank进行排列。

Customer_id  item_id rank_item
  23            2      3
  23            2      3
  23            4      2
  25            5      1
  25            4      2
Run Code Online (Sandbox Code Playgroud)

我期望的输出是

Customer_id    item_list
  23             4,2
  25             5,4
Run Code Online (Sandbox Code Playgroud)

我使用的代码是

 SELECT
    customer_id,
    concat_ws(',',collect_list (string(item_id))) AS item_list
FROM
    table1
GROUP BY
    customer_id
ORDER BY
    item_rank
Run Code Online (Sandbox Code Playgroud)

Chr*_*oth 8

您可以使用子查询来获取结果集(customer_id,item_id,item_rank),并按item_rank对其进行排序,然后collect_set在外部查询中使用。

询问

WITH table1 AS (
    SELECT 23 AS customer_id, 2 AS item_id, 3 AS item_rank UNION ALL
    SELECT 23 AS customer_id, 2 AS item_id, 3 AS item_rank UNION ALL
    SELECT 23 AS customer_id, 4 AS item_id, 2 AS item_rank UNION ALL
    SELECT 25 AS customer_id, 5 AS item_id, 1 AS item_rank UNION ALL
    SELECT 25 AS customer_id, 4 AS item_id, 2 AS item_rank
)
SELECT
    subquery.customer_id,
    collect_set(subquery.item_id) AS item_id_set
FROM (
    SELECT
        table1.customer_id,
        table1.item_id,
        table1.item_rank
    FROM table1
    DISTRIBUTE BY
        table1.customer_id
    SORT BY
        table1.customer_id,
        table1.item_rank
) subquery
GROUP BY
    subquery.customer_id
;
Run Code Online (Sandbox Code Playgroud)

结果

    customer_id item_id_set
0   23  [4,2]
1   25  [5,4]
Run Code Online (Sandbox Code Playgroud)

子查询用于DISTRIBUTE BY确保特定customer_id路由的所有行均到达同一reducer。然后,它使用SORT BY的排序customer_iditem_rank每个减速器内。我希望这足以满足要求,因为我没有注意到对最终结果集进行整体排序的要求。(如果需要按总顺序排序customer_id,那么我认为查询将必须使用ORDER BY,这将导致执行速度变慢。)

在内部,collect_setUDAF使用Java LinkedHashSet,它是一个保留顺序的集合,因此子查询中使用的排序顺序将在外部查询的集合中维护。这在Hive代码库中可见:

https://github.com/apache/hive/blob/release-2.0.0/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFMkCollectionEvaluator.java#L93

  • 谢谢克里斯,但是更大的数据集不会有问题吗?从我所看到的 Sort by 甚至 Cluster by 并不能确保全局排序 /sf/ask/960053111/ (2认同)