一列中的行号,但随后使用另一列重新排序

时间:2015-04-02 02:14:37

标签: python sql postgresql sqlalchemy postgresql-9.3

我汇总(汇总)购买表中的一些数据,按每个地区的总金额汇总。

数据类似于以下内容:

| id | region | purchase_amount |
| 1  | A      | 30              |
| 2  | A      | 35              |
| 3  | B      | 41              |

汇总后的数据如下所示,按total_purchases排序:

| region  | total_purchases |
|   B     |  1238           |
|   A     |  910            |
|   D     |  647            |
|   C     |  512            |

我希望获得每个地区的排名,按total_purchases排序。我可以使用row_number(目前使用SQLAlchemy)执行此操作,这会产生如下表格:

| rank | region  | total_purchases |
|  1   |   B     |  1238           |
|  2   |   A     |  910            |
|  3   |   D     |  647            |
|  4   |   C     |  512            |

然而,还有一个我想要分组的专栏:<'s>  我想要地区' C'永远是第一排,但要保持排名。

理想情况下,这会使表格看起来像:

| rank | region  | total_purchases |
|  4   |   C     |  512            |
|  1   |   B     |  1238           |
|  2   |   A     |  910            |
|  3   |   D     |  647            |

我可以做其中一个,但我似乎无法将这两个功能结合在一起。如果我使用row_number()函数,我会得到正确的排序。

我可以带来这个地区' C'使用2列的排序始终排在最前面:

ORDER BY
     CASE WHEN region = 'C' THEN 1 ELSE 0 DESC,
     total_purchases DESC

但是,我似乎无法将这两个要求合并到同一个查询中。

3 个答案:

答案 0 :(得分:2)

使用CTE来实现这一点,将您的ROW_NUMBER放在主查询中

;WITH C AS(
    SELECT ROW_NUMBER() OVER (ORDER BY total_purchases DESC) AS Rn
           ,region
           ,total_purchases
    FROM your_table
)
SELECT *
FROM C
ORDER BY (CASE WHEN region = 'C' THEN 1 ELSE 0 END) DESC
         ,total_purchases DESC

答案 1 :(得分:1)

这有用吗?

select row_number() over (order by total_purchases desc) as rank,
       region, total_purchases
from table t
order by (case when region = 'C' then 1 else 0 end) desc, total_purchases desc;

答案 2 :(得分:0)

这是关于Postgres的,我们有一个正确的boolean类型,可以直接按任何布尔表达式排序:

SELECT rank() OVER (ORDER BY sum(purchase_amount) DESC NULLS LAST) AS rank
     , region
     , sum(purchase_amount) AS total_purchases
FROM   purchases 
GROUP  BY region
ORDER  BY (region <> 'C'), 1, region;  -- region as tiebreaker

解释

  • 窗口函数在聚合函数之后执行,因此我们不需要子查询或CTE。

  • NULLS LAST

  • 最终1引用了SELECT列表中的序号位置1,因此我们不必重复表达。

  • ORDER BY (region <> 'C')

  • window function rank()似乎已经足够了。与row_number()相反,相等total_purchases等级相同。要在这种情况下打破可能的关系并获得稳定的结果,请将region(或其他)作为最后一项添加到ORDER BY
    如果您使用row_number()且仅使用ORDER BY sum(purchase_amount),则相等的总数可以在两个单独的调用中切换位置。您可以在ORDER BY的{​​{1}}子句中添加另一个项目以获得类似的结果,但相等的row_number()更适合等于rank我说的。< / p>