列出 MySQL 中共享群组的最常见项目

List most common item sharing a group in MySQL

table 组 ID 和项目如下:

group   item
-------------
1         A       
1         B
1         C    
1         D     

2         D     
2         A   
2         B   

3         B 
3         C 
3         D

4         A 
4         D 
4         E 

5         A 
5         D 

如何检索与指定项目一起找到的最常见项目?在上面的 table 中,A​​ 最常见的项目是 D.

您可以self-join、聚合和过滤:

select item, item2 most_frequent_item, cnt
from (
    select t1.item item, t2.item item2, count(*) cnt, 
        rank() over(partition by t1.item order by count(*) desc) rn
    from mytable t1
    inner join mytable t2 on t1.grp = t2.grp and t1.item <> t2.item
    group by t1.item, t2.item
) t
where rn = 1

这仅适用于 MySQL 8.0(其中 window 函数可用),并允许平局(如果有的话)(如果您不想要平局,请使用 row_number() 而不是rank()).

Demo on DB Fiddle:

item | most_frequent_item | cnt
:--- | :----------------- | --:
A    | D                  |   4
B    | D                  |   3
C    | B                  |   2
C    | D                  |   2
D    | A                  |   4
E    | A                  |   1
E    | D                  |   1

在早期版本中,这有点复杂。一个选项使用 having 子句:

select t1.item item, t2.item most_frequent_item, count(*) cnt
from mytable t1
inner join mytable t2 on t1.grp = t2.grp and t1.item <> t2.item
group by t1.item, t2.item
having count(*) = (
    select count(*) cnt
    from mytable t11
    inner join mytable t21 on t11.grp = t21.grp and t11.item <> t21.item
    where t11.item = t1.item
    group by t11.item, t21.item
    order by count(*) desc limit 1
)
order by t1.item

平局时最高者优先:

select item,substring(max(related_items),11) most_common
from (
    select t1.item,concat(lpad(count(*),10,'0'),t2.item) related_items
    from t t1
    join t t2 on t1.grp=t2.grp and t1.item != t2.item
    group by t1.item,t2.item
) related_items
group by item

Fiddle: https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=47ad17e48d8a24128e4ca00d81b9813a

如果您不关心平局,那么 group by item 并获得出现次数最多的第一项:

select item
from tablename
where item <> 'A' and `group` in (select `group` from tablename where item = 'A')
group by item
order by count(*) desc limit 1

参见demo
结果:

> | item |
> | :--- |
> | D    |