如何使用 mySQL 返回另一列中每个值的最常见列值?

Posted

技术标签:

【中文标题】如何使用 mySQL 返回另一列中每个值的最常见列值?【英文标题】:How do I return the most common column value for each value in another column using mySQL? 【发布时间】:2020-03-29 18:44:45 【问题描述】:

我正在寻找一个棘手的 mysql 查询来为另一列中的每个值返回最常见的列值。我可以使用 php 来处理每个结果,但是用一个查询来做会更酷:)

例如,如果有一个这样的表,称为“事务”:

Id  payee   exp     category    
1   Amazon  25.00   Gifts
2   Amazon  30.21   Books
3   Amazon  12.98   Gifts
4   Amazon  15.00   Groceries
5   Amazon  14.54   Gifts
6   Alibaba 55.55   Stock
7   Alibaba 99.00   Stock
8   Alibaba 12.00   Fun
…

我想要的结果是这样的:

payee   count(payee)    category
Amazon  3               Gifts
Alibaba 2               Stock
…

我可以这样做:

SELECT `payee`, COUNT(`payee`), `category` FROM `transactions` WHERE 1 GROUP BY category ORDER BY COUNT(`payee`) DESC 

并接近我想要的:

Amazon  3   Gifts
Alibaba 2   Stock
Amazon  1   Books
Amazon  1   Groceries
Alibaba 1   Fun

但我不想要非最大计数(例如 Amazon、1、Books)。

我必须做一个子查询吗?还是用在?

【问题讨论】:

【参考方案1】:

您可以使用having 子句中的相关子查询过滤现有查询的结果,如下所示:

select payee, count(*), category 
from transactions t
group by payee, category 
having count(*) = (
    select count(*) 
    from transactions t1 
    where t1.payee = t.payee 
    group by category
    order by count(*) desc limit 1
)
order by count(*) desc

Demo on DB Fiddle

收款人 |计数(*) |类别 :-------- | --------: | :-------- 亚马逊 | 3 |礼物 阿里巴巴 | 2 |库存

或者,如果您正在运行 MySQL 8.0,您可以使用窗口函数 rank() over() 对每个收款人的类别进行排名,并过滤每个组的顶部记录:

select payee, cnt, category
from (
    select 
        payee, 
        count(*) cnt, 
        category, 
        rank() over(partition by payee order by count(*) desc) rn
    from transactions 
    group by category, payee
) t
where rn = 1

Demo on DB Fiddle

【讨论】:

以上是关于如何使用 mySQL 返回另一列中每个值的最常见列值?的主要内容,如果未能解决你的问题,请参考以下文章

使用 R 根据另一列中的类别计算列和列表之间常见值的百分比

获取 SQL 中另一列的每个值的最常见值

如何使用MySQL查询某个列中相同值的数量统计

如果匹配,如何合并两个数据帧并从新列中的另一列返回数据?

如果数组列中有多条具有相同值的记录 - 取一条具有另一列最小值的记录

MySQL - 如何根据另一列中的唯一值转置一列中的单元格?