计算 SQL 中计数相对于类别的百分比

Posted

技术标签:

【中文标题】计算 SQL 中计数相对于类别的百分比【英文标题】:Calculate percentages of count in SQL relative to the category 【发布时间】:2021-03-22 15:23:47 【问题描述】:

我在 mysql 工作。 最初我有一个如下所示的表格:

我的任务是计算等待时间长的人和等待时间短的人取消预订的百分比。 经过一些操作,我想出了以下代码:

SELECT
CASE WHEN days_in_waiting_list > (SELECT AVG(days_in_waiting_list) FROM Bookings) THEN 'Long wait'
ELSE 'Short wait' 
END AS waiting, 
is_canceled, COUNT(*), count(*) * 100.0 / sum(count(*)) over() AS perc_cancelled
FROM Bookings
GROUP BY waiting, is_canceled;

结果表:

但我希望计算类别的百分比,而不是整个表格。因此,Short wait 中的百分比总和等于 100,Long wait 也是如此。我希望它是这样的:

waiting is_cancelled perc
Short wait 0 0.61
Short wait 1 0.39
Long wait 0 0.32
Long wait 1 0.68

有没有办法做到这一点?我知道可以使用 over(partition by waiting),但它给了我错误

错误代码:1054。“window partition by”中的未知列“waiting”

【问题讨论】:

@Strawberry 对不起,我不知道该怎么做,但我会研究这个话题,谢谢! 【参考方案1】:

我会使用窗口函数来计算平均值,然后进行聚合:

select waiting, is_cancelled, 
    count(*) / sum(count(*)) over(partition by waiting) as ratio
from (
    select b.*, 
        case when days_in_waiting_list > avg(days_in_waiting_list) over()
            then 'Long Wait'
            else 'Short wait'
        end as waiting
    from bookings b
) b
group by waiting, is_cancelled
order by waiting, is_cancelled

【讨论】:

我不知道为什么其他解决方案对我不起作用,也许我在 MySQL 上有一个旧版本,但这有效!非常感谢:)【参考方案2】:

您希望按类别计算百分比,因此 perc_cancelled 需要按等待类别分组

count() * 100.0 / sum(count()) over(partition by waiting) AS perc_cancelled

【讨论】:

是的,我也有同样的想法。但它给了我一个错误“'window partition by'中的未知列'等待'” 我刚刚在 MariaDB 10.5.8 中尝试过,它工作正常...【参考方案3】:
WITH cte AS (
SELECT
CASE WHEN days_in_waiting_list > (SELECT AVG(days_in_waiting_list) FROM Bookings) 
THEN 'Long wait'
ELSE 'Short wait' 
END AS waiting, 
is_canceled,
COUNT(*) as subTotal, 
sum(count(*) over (partition by waiting ORDER BY is_canceled ASC) as totalSum,
FROM Bookings
GROUP BY waiting, is_canceled;
)
SELECT waiting,
is_canceled,
subTotal* (100.0)/totalSum as percentage
FROM cte
group by waiting,is_canceled

【讨论】:

非常感谢您的意见!但它告诉我有一个语法错误,我似乎无法弄清楚在哪里。 错误代码:1064。您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取正确的语法,以便在第 7 行的“as totalSum, subTotal* (100.0)/totalSum as percent FROM Bookings GROUP BY wai”附近使用 现在可以试试吗?【参考方案4】:

仅使用相关数据和 40 个随机行创建表:

CREATE TABLE test (
  id INT AUTO_INCREMENT PRIMARY KEY,
  is_canceled INT DEFAULT FLOOR(RAND() * 2),
  days_in_waiting_list INT DEFAULT FLOOR(RAND() * 100)
);
INSERT INTO test () VALUES (), (), (), (), (), (), (), (), (), ();
INSERT INTO test () VALUES (), (), (), (), (), (), (), (), (), ();
INSERT INTO test () VALUES (), (), (), (), (), (), (), (), (), ();
INSERT INTO test () VALUES (), (), (), (), (), (), (), (), (), ();

你真的很接近,只需添加PARTITION BY waiting

SELECT
  CASE WHEN days_in_waiting_list > (
    SELECT AVG(days_in_waiting_list)
    FROM test
  ) THEN 'Long' ELSE 'Short' END AS waiting,
  is_canceled,
  COUNT(*),
  COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (PARTITION BY waiting)
FROM test
GROUP BY waiting, is_canceled;
waiting is_canceled count(*) count() / sum(count()) over (partition by waiting)
Long 0 10 58.82353
Long 1 7 41.17647
Short 0 15 65.21739
Short 1 8 34.78261

【讨论】:

以上是关于计算 SQL 中计数相对于类别的百分比的主要内容,如果未能解决你的问题,请参考以下文章

在访问报告中计数

Elasticsearch - 计算嵌套聚合相对于父存储桶的百分比

计算相对于给定总体的百分位排名

在 SQL 中计算总行数的百分比

鼠标/手指相对于元素的坐标(px转百分比)

前端面试CSS环节问题 toptranslateY这种属性如果使用百分比,是相对于谁的百分比