SQL: ранжирование по группам без суммирования или объединения - PullRequest
0 голосов
/ 18 октября 2019

Мне нужно вычислить сумму (значение) для групп в моем наборе данных, а затем ранжировать группы на основе этой суммы.

Вот примерный набор данных и результат. Я хочу знать, какая из групп CYL имеет наибольшее общее количество миль на галлон (я знаю, что это бессмысленный результат!) И рейтинг групп CYL.

Данные:

| model               | mpg  | cyl | gear | 
|---------------------|------|-----|------| 
| Mazda RX4           | 21   | 6   | 4    | 
| Mazda RX4 Wag       | 21   | 6   | 4    | 
| Datsun 710          | 22.8 | 4   | 4    | 
| Hornet 4 Drive      | 21.4 | 6   | 3    | 
| Hornet Sportabout   | 18.7 | 8   | 3    | 
| Valiant             | 18.1 | 6   | 3    | 
| Duster 360          | 14.3 | 8   | 3    | 
| Merc 240D           | 24.4 | 4   | 4    | 
| Merc 230            | 22.8 | 4   | 4    | 
| Merc 280            | 19.2 | 6   | 4    | 
| Merc 280C           | 17.8 | 6   | 4    | 
| Merc 450SE          | 16.4 | 8   | 3    | 
| Merc 450SL          | 17.3 | 8   | 3    | 
| Merc 450SLC         | 15.2 | 8   | 3    | 
| Cadillac Fleetwood  | 10.4 | 8   | 3    | 
| Lincoln Continental | 10.4 | 8   | 3    | 
| Chrysler Imperial   | 14.7 | 8   | 3    | 
| Fiat 128            | 32.4 | 4   | 4    | 
| Honda Civic         | 30.4 | 4   | 4    | 
| Toyota Corolla      | 33.9 | 4   | 4    | 
| Toyota Corona       | 21.5 | 4   | 3    | 
| Dodge Challenger    | 15.5 | 8   | 3    | 
| AMC Javelin         | 15.2 | 8   | 3    | 
| Camaro Z28          | 13.3 | 8   | 3    | 
| Pontiac Firebird    | 19.2 | 8   | 3    | 
| Fiat X1-9           | 27.3 | 4   | 4    | 
| Porsche 914-2       | 26   | 4   | 5    | 
| Lotus Europa        | 30.4 | 4   | 5    | 
| Ford Pantera L      | 15.8 | 8   | 5    | 
| Ferrari Dino        | 19.7 | 6   | 5    | 
| Maserati Bora       | 15   | 8   | 5    | 
| Volvo 142E          | 21.4 | 4   | 4    | 

Это желаемый результат :

| cyl | gear | SUM([MPG]) | sum_mpg_by_group  | RANK | 
|-----|------|------------|-------------------|------| 
| 4   | 3    | 21.5       | 293.3             | 1    | 
| 4   | 5    | 56.4       | 293.3             | 1    | 
| 4   | 4    | 215.4      | 293.3             | 1    | 
| 6   | 5    | 19.7       | 138.2             | 3    | 
| 6   | 3    | 39.5       | 138.2             | 3    | 
| 6   | 4    | 79         | 138.2             | 3    | 
| 8   | 5    | 30.8       | 211.4             | 2    | 
| 8   | 3    | 180.6      | 211.4             | 2    | 

Требования:

Это должно быть сделано без subqueries, with операторов или joins - я знаю, можно ли это сделать сих, но по причинам производительности и краткости я хочу исследовать варианты без них.

Другими словами, есть ли способ получить RANK группы на основе GROUPED SUM без использования объединений?

Следующее приводит меня почти туда, но, очевидно, оператор RANK () не выполняетсятак что я просто пропускаю последний столбец.

-- Non working query

select cyl
    , gear
    , sum(mpg) as sum_mpg
    , sum(sum(mpg)) over (PARTITION BY cyl) as sum_mpg_by_group
  --, rank() over (group by model order by sum(mpg) desc) as RANK
from sample_data_mtcars
group by cyl, gear

Ответы [ 2 ]

2 голосов
/ 18 октября 2019

Это звучит как агрегация и dense_rank():

select s.*,
       dense_rank() over (order by sum_mpg_group desc) as ranking
from (select cyl, gear, sum(mpg) as sum_mpg,
             sum(sum(mpg)) over (partition by cyl) as sum_mpg_group
      from sample_data_mtcars
      group by cyl, gear
     ) s
1 голос
/ 19 октября 2019

Вы должны иметь возможность группировать по функции OLAP или вызывать функцию OLAP_FUNCTION () OVER ( an-OLAP-функция ), чтобы это сделать, что невозможно.

Почему уклоняться от вложенного запроса? Vertica имеет конвейерный параллелизм: пока строки проходят через внутренний запрос (или выражение общей таблицы), другой набор операторов работает над внешним запросом, перехватывая строки, поступающие из внутреннего запроса, и обрабатывая их дальше. Питается ресурсами, но не медленно.

Попробуйте:

Сформулируйте ваш запрос как вложенный запрос, как предложил Гордон, и поставьте перед ним ключевое слово PROFILE. Когда вы это сделаете, соберите транзакции_id и Statement_id, которые возвращаются при запуске профилирования этого запроса.

Затем вы можете проверить системную таблицу execution_engine_profiles, отфильтровав по транзакции_id / Statement_id, и посмотреть, сколько операторов былоработает, проверьте истекшее время и процессорное время, чтобы увидеть, что несколько операторов работают параллельно ...

...