Поиск записей, которые чаще всего встречаются вместе в SQL

#mysql #sql

#mysql #sql

Вопрос:

У меня есть таблица ингредиентов:

 ing_id, ing_name
1      , ing1
...
 

таблица рецептов:

 rec_id, rec_name
1     , rec1
...
 

и таблица, показывающая связь между этими двумя:

 id, ing_id, rec_id
1,  1, 1
2,  1, 2
3,  2, 1
4,  3, 3
...
 

Как я могу найти ингредиенты, которые чаще всего используются в одном и том же рецепте?

Комментарии:

1. Что вы подразумеваете под словом «чаще всего»? Вы думаете о том, чтобы перечислить комбинацию ингредиентов и их количество по рецепту? Если в рецепте есть 3 ингредиента, это будет считаться ing1 2, ing1 3, ing2 3. Если в рецепте 4 ингредиента, это будет подсчет ing1 2, ing1 3, ing1 4, ing2 3, ing2 4, ing3 4, ing1 2 3, ing1 2 4, ing1 3 4 и т.д., а затем сортировка по наибольшемусначала посчитайте. Это то, чего ты хочешь?

2. Обновил пример, чтобы лучше проиллюстрировать проблему: в приведенном выше примере ингредиенты 1 и 2 имеют один общий рецепт (rec_id = 1), в то время как ингредиенты 1 и 3 не имеют общего рецепта. То же самое для ингредиентов 2 и 3. Таким образом, мы хотели бы, чтобы результат был равен 1 и 2, поскольку это комбинация с наиболее распространенными рецептами (один> ноль).

3. Допустим, у вас было 5 разных рецептов. Recipe1 имел ингредиенты i1, i2 и i3. Recipe2 имел i1, i2, i3, i4, i5. Recipe3 имел i3, i4, i7, i8. Recipe4 имел i3, i4, i5, i6, i7, i9, i10. Recipe5 были все ингредиенты i1 ..i10. Как будет выглядеть ваш вывод?

4. 3 и 4. Они оба появляются вместе в четырех рецептах (2,3,4,5), что выше, чем у любой другой пары ингредиентов.

5. Вам лучше выполнять эту математику вне SQL на языке программирования по вашему выбору. В приведенном выше примере, если бы i2 был в тех же рецептах, что и i3, вы бы хотели получить выходные данные i2, i3 и i4. Это означает, что вы хотите увидеть, какая комбинация ингредиентов из 2 чаще всего встречается во всех рецептах.

Ответ №1:

Вы можете использовать самосоединение и group by :

 select c1.ing_id, c2.ing_id, count(*)
from connections c1 join
     connections c2
     on c1.rec_id = c2.rec_id and c1.ing_id < c2.ing_id
group by c1.ing_id, c2.ing_id
order by count(*) desc;
 

Если вам действительно нужны имена вместо идентификаторов, вам понадобятся еще два соединения, чтобы ввести их.

Комментарии:

1. Это намного проще, чем я думал!