SQL:按组排序,无需汇总或加入

时间:2019-10-18 00:37:17

标签: mysql sql vertica

我需要计算数据集中各组的总和(值),然后根据该总和对各组进行排名。

这是示例数据集和结果。我想知道哪个CYL组的总mpg最高(我知道这是荒谬的结果!)以及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    | 

要求:

这应该在没有subquerieswith语句或joins的情况下完成-我知道是否可以使用它们,但是出于性能和简洁的原因,我想探索没有它们的选项。

换句话说,有没有一种方法可以在不使用联接的情况下基于GROUPED SUM获得组的RANK?

以下内容将我带到了那里,但是很显然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 个答案:

答案 0 :(得分:2)

这听起来像聚合和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 :(得分:1)

您应该能够按OLAP函数分组,或者能够通过OLAP_FUNCTION()OVER( an-OLAP-function )来做到这一点,这是不可能的。

为什么要避开嵌套查询? Vertica具有管道并行性:当行流过内部查询(或“公共表表达式”)时,另一组运算符正在外部查询上工作,捕获来自内部查询的行并进行进一步处理。消耗资源,但并不慢。

尝试一下:

按照Gordon的建议,将查询构造为嵌套查询,并将PROFILE关键字放在其前面。这样做时,请收集启动该查询的概要分析时返回的transaction_id和statement_id。

然后,您可以检查execution_engine_profiles系统表,并按transaction_id / statement_id进行过滤,并查看有多少操作员在工作,检查经过的时间和CPU时间以查看有几个操作员并行运行...