有几种方法可以做到这一点。一种方法是使用UNNEST 将映射转换为行,每个映射条目一行。然后,您可以使用rank() 窗口函数为每个名称的宠物分配排名,之后您只选择排名最高的项目。
WITH people (name, pets) AS (
VALUES
('Andy', map_from_entries(array[('dog', 2), ('cat', 1), ('bird', 4)])),
('John', map_from_entries(array[('tiger', 3), ('elephant', 1), ('fish', 2)])),
('Mary', map_from_entries(array[('dog', 2), ('pig', 2)]))
)
SELECT name, pet AS max_pet
FROM (
SELECT name, pet, count,
rank() OVER (PARTITION BY name ORDER BY count DESC) rnk
FROM people
CROSS JOIN UNNEST(pets) AS t (pet, count)
)
WHERE rnk = 1;
name | max_pet
------+---------
Andy | bird
John | tiger
Mary | dog
Mary | pig
(4 rows)
使用UNNEST 简单易懂,但如果需要与其他操作结合使用,或者名称重复,则效果不佳。
另一种方法是使用map_entries() 将地图转换为数组,使用filter() 选择计数等于最大计数的宠物,然后使用transform() 仅返回宠物名称。此时,您有一个最大宠物数组。然后,您可以将UNNEST 分成多行,或将其保留为数组以供进一步处理。 filter() 和 transform() 使用 lambda expression,这是 SQL 的 Presto 特定扩展。
WITH people (name, pets) AS (
VALUES
('Andy', map_from_entries(array[('dog', 2), ('cat', 1), ('bird', 4)])),
('John', map_from_entries(array[('tiger', 3), ('elephant', 1), ('fish', 2)])),
('Mary', map_from_entries(array[('dog', 2), ('pig', 2)]))
)
SELECT
name,
transform(
filter(
map_entries(pets),
e -> e[2] = array_max(map_values(pets))),
e -> e[1]) AS max_pets
FROM people;
name | max_pets
------+------------
Andy | [bird]
John | [tiger]
Mary | [dog, pig]
(3 rows)