In Table 1, I have customer_id, item_id and item_rank (rank of item according to some sales). I want to collect a list of items for each customer_id and arrange them according to item_rank.
Customer_id item_id rank_item
23 2 3
23 2 3
23 4 2
25 5 1
25 4 2
The output I expect is
Customer_id item_list
23 4,2
25 5,4
The code I used was
SELECT
customer_id,
concat_ws(',',collect_list (string(item_id))) AS item_list
FROM
table1
GROUP BY
customer_id
ORDER BY
item_rank
You can use a sub-query to get a result set of (customer_id, item_id, item_rank), sorted by item_rank, and then use collect_set
in the outer query.
Query
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
;
Results
customer_id item_id_set
0 23 [4,2]
1 25 [5,4]
The sub-query uses DISTRIBUTE BY
to guarantee that all rows for a particular customer_id
route to the same reducer. It then uses SORT BY
to sort by customer_id
and item_rank
within each reducer. I expect this is sufficient for the requirements, because I didn't notice a requirement for total ordering of the final result set. (If total ordering by customer_id
is a requirement, then I think the query would have to use ORDER BY
, which would cause slower execution.)
Internally, the collect_set
UDAF uses a Java LinkedHashSet
, which is an order-preserving collection, so the same sort order used in the sub-query will be maintained in the outer query's set. This is visible in the Hive codebase here:
https://github.com/apache/hive/blob/release-2.0.0/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFMkCollectionEvaluator.java#L93
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With