用两列mysql分组的最频繁值

时间:2019-02-20 13:26:00

标签: mysql group-by distinct

我有一个包含两列的表(测试)(名称为varchar(5),cnt int)

表名称:test

+--------+-------------+
| column |    type     |
+--------+-------------+
| name   | varchar (5) |
| 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

我尝试了类似的查询

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

但是我得到的结果

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

这是sql小提琴 link

6 个答案:

答案 0 :(得分:2)

LIMIT相关的查询可用于查找最常出现的值:

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

答案 1 :(得分:1)

这是使用窗口函数执行此操作的一种方法:

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;

enter image description here

Demo

编辑:

这是我尝试使用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;

Demo

这里的困难在于,我们首先必须通过namecnt进行汇总,以找到每个组的最大计数。然后,必须对其进行子查询以找到每个具有最高计数的name的组。最后,在给定的name恰好有两个子组的情况下,还需要另一种汇总才能找到具有最低 cnt值的name组相同的计数(例如B)。

答案 2 :(得分:1)

如果您想在抽奖时报告所有条目

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)

答案 3 :(得分:0)

尝试使用相关子查询,如下所示

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更改为子查询版本

答案 4 :(得分:0)

这项工作:

  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

答案 5 :(得分:0)

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

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