Запрос Presto: найдите ключ с максимальным значением на карте - PullRequest
1 голос
/ 02 августа 2020

У меня есть таблица

Name  pets
--------------
Andy  {dog:2, cat:1, bird:4}
John  {tiger:3, elephant:1, fish:2}
Mary  {dog:2, pig:2}

Я хочу найти тип питомца с максимальным количеством для каждого человека. В случае t ie продублируйте строку для каждого питомца. Результат должен выглядеть так:

Name  max_pet
------------------
Andy  bird
John  tiger
Mary  dog
Mary  pig

В настоящее время я экспортировал таблицу и сделал это в python. Но мне интересно, могу ли я добиться этого с помощью запроса Presto / SQL? Спасибо!

1 Ответ

3 голосов
/ 02 августа 2020

Есть несколько способов сделать это. Один из подходов - использовать 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;

Использование UNNEST прост для понимания, но не работает, если вам нужно комбинировать его с другими операциями или если у вас есть повторяющиеся имена.

Другой подход - преобразовать карту в массив с помощью map_entries(), используйте filter(), чтобы выбрать питомца (ов) с количеством, равным максимальному количеству, затем используйте transform(), чтобы вернуть только питомца название. На данный момент у вас есть максимальное количество питомцев. Затем вы можете UNNEST разбить его на несколько строк или сохранить как массив для дальнейшей обработки. filter() и transform() используют лямбда-выражение , которое является спецификацией Presto c, расширением до SQL.

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;
...