Использование суммы столбца запрашиваемой таблицы в случае, когда (Hive) - PullRequest
0 голосов
/ 07 января 2020

Упрощенный пример:

В куст у меня есть таблица t с двумя столбцами:

Name, Value
Bob, 2
Betty, 4
Robb, 3

Я хочу сделать case when, что использует сумму столбца Значение:

Select
    Name
    , CASE 
        When value>0.5*sum(value) over () THEN ‘0’
        When value>0.9*sum(value) over () THEN ‘1’
        ELSE ‘2’
        END as var
From table

Мне не нравится тот факт, что sum(value) over () вычисляется дважды. Есть ли способ вычислить это только один раз. Добавлен поворот, я хочу сделать это в одном запросе, поэтому без объявления пользовательских переменных .

Я думал о скалярных запросах:

With total as
 (Select sum(value) from table)
Select 
    Name
    , CASE 
         When value>0.5*(select * from total) THEN ‘0’
         When value>0.9*(select * from total)THEN ‘1’
         ELSE ‘2’
         END as var 
From table;

Но это не работает.

TLDR : есть ли способ упростить первый запрос без пользовательских переменных?

Ответы [ 3 ]

1 голос
/ 07 января 2020

Не беспокойся об этом. Пусть оптимизатор беспокоится об этом. Но вы можете использовать подзапрос или CTE, если не хотите повторять выражение:

select Name,
       (case when value > 0.5 * total then '0'
             when value > 0.9 * total then '1' 
             else '2'
        end) as var
From (select t.*, sum(value) over () as total
      from table t
     ) t;
0 голосов
/ 08 января 2020

Поскольку ввод-вывод является основным фактором, замедляющим запросы Hive, мы должны стремиться сократить количество этапов, чтобы повысить производительность.

Так что лучше не использовать подзапрос или CTE здесь.

Попробуйте это SQL с предложением глобального окна:

select 
    name,
    case
        when value > 0.5*sum(value) over w then '0'
        when value > 0.9*sum(value) over w then '1'
        else '2'
        end as var
from my_table
window w as (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)

В этом случае window clause является рекомендуемым способом уменьшения повторения кода.

Оконная обработка и агрегация sum будут вычислены только один раз. Вы можете запустить explain select..., подтверждая, что будет запущен только ОДИН значимый этап MR.

Редактировать:
1. Простое предложение select в подзапросе не о чем беспокоиться. Его можно перенести на последнюю фазу подзапроса, чтобы избежать дополнительной стадии MR.
2. Два идентичных агрегата, находящихся в одном и том же блоке запроса, будут оцениваться только один раз. Так что не беспокойтесь о возможном повторном расчете.

0 голосов
/ 07 января 2020

Перекрестное объединение подзапроса, извлекающего сумму из таблицы:

Select
    t.Name
    , CASE 
        When t.value>0.9*tt.value THEN '1'
        When t.value>0.5*tt.value THEN '0'
        ELSE '2'
        END as var
From table t cross join (select sum(value) value from table) tt

и изменяют порядок предложений WHEN в выражении CASE, поскольку во втором случае никогда не удастся.

...