I have a table (test) with two columns (name varchar(5), cnt int)
Table Name: test
+--------+-------------+
| column | type |
+--------+-------------+
| name | varchar (5) |
| cnt | int |
+--------+-------------+
and have values
+------+-----+
| name | cnt |
+------+-----+
| A | 1 |
| A | 1 |
| A | 1 |
| A | 2 |
| B | 1 |
| B | 2 |
+------+-----+
I like to get result of most frequent count with unique name
So the expected result will be
+------+------+-------+
| name | cnt | count |
+------+------+-------+
| A | 1 | 3 |
| B | 1 | 1 |
+------+------+-------+
As A has two 1 and one 2 and B has one 1 and one 2
I tried the query like
select distinct name, cnt, COUNT(cnt) as count
from test
group by cnt, name
order by count desc
But the result I am getting
+------+------+-------+
| name | cnt | count |
+------+------+-------+
| A | 1 | 3 |
| A | 2 | 1 |
| B | 1 | 1 |
| B | 2 | 1 |
+------+------+-------+
here is the sql fiddle link
A correlated query with LIMIT
could be used to find the most occurring value:
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
Here is one way to do this using window functions:
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;
Edit:
Here is my attempt at a pre-MySQL 8+ solution:
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;
The difficulty here is that we first have to aggregate by both name
and cnt
, to find the max counts for each group. Then, this has to be subqueried to find the group for each name
having the highest count. Finally, another aggregation is required to find the name
group with the lowest cnt
value, in the case that a given name
happens to have two sub groups with the same count (eg B
).
If you want to report all entries in the event of a draw
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)
try like below using corelated subquery
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
As for B both frequency is same that's why both will come on output, You can change this cte to subquery version
this work:
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
I did something myself But not sure its efficient to do. As My table might have lots of entry.
select * from
(select distinct name, cnt, COUNT(cnt) as count
from test
group by cnt, name
order by count desc) A
group by name
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.