列出 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()
).
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 |
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()
).
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 |