【问题标题】:Get grouped value divided by total获取分组值除以总数
【发布时间】:2023-03-29 16:45:01
【问题描述】:

我有一张这样的桌子:

+----+---------------+----------+
| id | city          | price    |
+----±---------------±----------+
| 1  | Paris         | 2.000,00 |
| 2  | London        | 500,00   |
| 3  | Paris         | 500,00   |
| 4  | Madrid        | 1.000,00 |
±----±---------------±----------±

还有这样的请求:

select
    city,
    sum(price)
from orders
group by city
order by sum(price) desc

这给了我这样的结果:

+----------+---------------+
| city     | SUM(price)    |
+----------±---------------±
| Paris    | 2.500,00      |
| Madrid   | 1.000,00      |
| London   | 500,00        |
±----------±---------------±

我想要的是第三列中每个城市的价格比率,这样巴黎就有 62.50 % 等等,像这样:

+----------+---------------+-------------+
| city     | SUM(price)    | Ratio       |
+----------±---------------±-------------+
| Paris    | 2.500,00      | 62,50       |
| Madrid   | 1.000,00      | 25          |
| London   | 500,00        | 12,50       |
±----------±---------------±-------------±

目前,我必须在获得第一个结果集后计算 PHP 中的最后一列。我想知道是否有任何方法可以直接在 SQL 中执行此操作?

【问题讨论】:

    标签: postgresql group-by resultset


    【解决方案1】:

    您可以使用子查询来获取总价:

    select
        city,
        sum(price),
        100.0 * sum(price) / (select sum(price) from Orders) AS Ratio
    from Orders
    group by city
    order by sum(price) desc
    

    Demo here

    您也可以使用CROSS JOIN:

    select
        city,
        sum(price),
        100.0 * sum(price) / t.total_price AS Ratio
    from Orders
    cross join (select sum(price) as total_price from Orders) AS t
    group by city
    order by sum(price) desc
    

    【讨论】:

    • 100.0 可能会更好地乘以得到小数。
    • 感谢您的回答。实际上,我有一个比这个更复杂的查询。我知道子查询是可能的,但我想知道是否有“更好”的方法(可能是窗口函数?)
    • @JuanCarlosOropeza 是的,没错,非常感谢。
    【解决方案2】:

    我建议使用 CTE 来提高阅读能力,但您将获得与 Giorgios 答案相同的性能。

    WITH cte0 as (
         SELECT *
         FROM Orders
         WHERE <filters>
    ),
    cte as (
         SELECT SUM(price) total
         FROM cte0 
    )
    SELECT city, sum(price), 100.0 * SUM(Price) /  cte.total
    FROM cte0 
    CROSS JOIN cte
    GROUP BY city
    

    【讨论】:

    • 使用 PostgreSQL,您必须将 GROUP BY 修改为 city, cte.total。这个解决方案确实有效,但它会让我将整个过滤器重复到WITH 选择部分。
    • 抱歉,不确定您的意思。也许您应该对您的问题进行更详细的描述
    • 但是如果您要添加过滤器,您可以在过滤器之前添加另一个cte0 并将其用于cte 和最终查询
    • 正如我在 Giorgos Betsos 的回答中所说的那样,我的实际查询中有很多 where 子句,为了便于阅读,我没有在此处粘贴这些子句。这不是一个真正的问题,只是它将用该解决方案建立一个巨大的请求。这就是我在下面的评论中提到window function 的原因。
    • 我不确定您所说的“您可以添加另一个cte0”是什么意思?你能举个例子吗?
    猜你喜欢
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 2023-04-03
    • 1970-01-01
    • 2015-10-17
    相关资源
    最近更新 更多