按两列分组的最频繁值mysql

按两列分组的最频繁值mysql,mysql,group-by,distinct,Mysql,Group By,Distinct,我有一个名为varchar5,cnt int的表测试 表名:测试 而且有价值 +------+-----+ | name | cnt | +------+-----+ | A | 1 | | A | 1 | | A | 1 | | A | 2 | | B | 1 | | B | 2 | +------+-----+ 我喜欢使用唯一的名称获取最频繁计数的结果 因此,预期的结果将是 +------+------+-------+ | na

我有一个名为varchar5,cnt int的表测试

表名:测试

而且有价值

+------+-----+
| name | cnt |
+------+-----+
| A    |   1 |
| A    |   1 |
| A    |   1 |
| A    |   2 |
| B    |   1 |
| B    |   2 |
+------+-----+
我喜欢使用唯一的名称获取最频繁计数的结果

因此,预期的结果将是

+------+------+-------+
| name | cnt  | count |
+------+------+-------+
| A    |    1 |     3 |
| B    |    1 |     1 |
+------+------+-------+
A有两个1和一个2,B有一个1和一个2

我试着这样问

选择不同的名称、cnt、COUNTcnt作为计数 从测试 按cnt、名称分组 按计数顺序描述 但是我得到的结果是

+------+------+-------+
| name | cnt  | count |
+------+------+-------+
| A    |    1 |     3 |
| A    |    2 |     1 |
| B    |    1 |     1 |
| B    |    2 |     1 |
+------+------+-------+

以下是sql FIDLE

这里有一种使用窗口函数实现此功能的方法:

WITH cte AS (
    SELECT name, cnt, COUNT(*) AS count,
        ROW_NUMBER() OVER (PARTITION BY name ORDER BY COUNT(*) DESC, cnt) rn
    FROM yourTable
    GROUP BY name, cnt
)

SELECT name, cnt, count
FROM cte
WHERE rn = 1;
编辑:

以下是我对MySQL 8+之前的解决方案的尝试:

SELECT t1.name, MIN(t1.cnt), MAX(t1.count)
FROM
(
    SELECT name, cnt, COUNT(*) AS count
    FROM yourTable
    GROUP BY name, cnt
) t1
INNER JOIN
(
    SELECT name, MAX(count) AS max_count
    FROM
    (
        SELECT name, cnt, COUNT(*) AS count
        FROM yourTable
        GROUP BY name, cnt
    ) t
    GROUP BY name
) t2
    ON t1.name = t2.name AND t1.count = t2.max_count
GROUP BY
    t1.name;

这里的困难在于,我们首先必须按名称和cnt进行聚合,以找到每组的最大计数。然后,必须对其进行子查询,以查找每个具有最高计数的名称的组。最后,如果给定名称恰好有两个具有相同计数的子组,例如B,则需要另一个聚合来查找具有最低cnt值的名称组。

请使用相关子查询尝试下面的方法

WITH yourTable AS (
    SELECT 'A' AS name, 1 AS cnt UNION ALL
    SELECT 'A', 1 UNION ALL
    SELECT 'A', 1 UNION ALL
    SELECT 'A', 2 UNION ALL
    SELECT 'B', 1 UNION ALL
    SELECT 'B', 2
),
cte2 as (
select  name, cnt, COUNT(*) as cn
from yourTable 
group by cnt, name
) select t1.* from cte2 t1 where t1.cn=( select max(cn) from cte2 t2 
                                        where t2.name=t1.name
                                     )

name    cnt     cn
A        1      3
B        1      1
B        2      1
对于B,两个频率相同,这就是为什么两个都会出现在输出上,您可以将此cte更改为子查询版本

  SELECT a.name,a.cnt,max(a.count) AS count FROM (
         SELECT distinct name, cnt, COUNT(cnt) as count
         FROM test
         GROUP BY name,cnt
 ) a
 GROUP BY a.name
 ORDER BY a.count DESC
具有限制的相关查询可用于查找最常出现的值:

SELECT name, cnt, COUNT(*) AS c
FROM t
WHERE cnt = (
    SELECT cnt
    FROM t AS x
    WHERE name = t.name
    GROUP BY cnt
    ORDER BY COUNT(*) DESC
    LIMIT 1
)
GROUP BY name, cnt

如果要在绘图时报告所有条目

select name,cnt,obs
from
(
select s.name,s.cnt,obs ,
    if(s.name <>@pname, @rn:=1,if(s.obs<>@pobs,@rn:=@rn+1,@rn:=@rn)) denserank,
    @pname:=s.name,
    @pobs:=s.obs
from
(
select t.name, t.cnt,count(*) obs
from t
group by t.name,t.cnt
) s
) t
where denserank = 1;

+------+------+-----+
| name | cnt  | obs |
+------+------+-----+
| A    |    1 |   3 |
| B    |    1 |   1 |
| B    |    2 |   1 |
+------+------+-----+
3 rows in set (0.03 sec)

我自己做了一些事情,但不确定这是否有效。因为我的表可能有很多条目

select * from 
(select distinct name, cnt, COUNT(cnt) as count
from test
group by cnt, name
order by count desc) A
group by name

A有3个1和1个2?如果B有一个1和一个2,为什么只显示1计数?你可能需要密集排名你使用的是哪个版本的mysql?抱歉,我在发布这个问题时额外添加了一行。我调整了answer@P.Salmonmysql版本14.14发行版5.7.19,对于Linux x86\u 64b,1和2看起来是一样的frequent@fa06你的评论根本不属于这里。@TimBiegeleisen,oppssorry@Atiq我已经给了你一个可以在你的MySQL版本上使用的选项。你的相关限制子查询有一个微妙的潜在问题。在出现平局(如B)的情况下,当前似乎会为每个名称组选择具有最大计数的较低cnt值。但这一点无法保证,至少不能仅基于SQL。我可以想到其他数据库,例如Postgres,您的查询可能会产生不正确的结果。OP没有提到如果计数相等会发生什么。RDBMS可以自由选择任何一种。但通过显式修改顺序很容易打破僵局,例如按计数*DESC、cnt排序-首选较小的值。良好保存+1。我喜欢你的答案胜过我的MySQL 5答案。但行数方法可能是最简单、最容易理解的方法。此查询无效,因为您在名称的外部查询中使用GROUP BY,但随后选择的是非聚合列。@TimBiegeleisen是否对其进行了测试?在MySQL的某些版本上。因此,您不应该将此作为推荐给其他人。您当前的输出与OP预期的不匹配。OP希望每个姓名都有一条记录,而不是2条。重新阅读问题。OP要求每个名称对应一行,而不是两行。但这是对会话变量的大胆使用,所以我将投票支持你。
select * from 
(select distinct name, cnt, COUNT(cnt) as count
from test
group by cnt, name
order by count desc) A
group by name