Найти в hasMany, где все условия верны

У меня есть эти таблицы:

продукты -> hasMany -> категории

Таблица: продукты

+----+--------+
| id | title  |
+----+--------+
|  1 | Prod 1 |
|  2 | Prod 2 |
|  3 | Prod 3 |
+----+--------+

Таблица: категории

+----+-------+------------+
| id | title | product_id |
+----+-------+------------+
|  1 | Cat 1 |          1 |
|  2 | Cat 2 |          1 |
|  3 | Cat 3 |          2 |
|  4 | Cat 1 |          1 |
+----+-------+------------+

Как я могу запросить продукты, которые находятся в обеих категориях «Cat 1» и «Cat 2», в моем примере я хочу найти только «Prod 1»


person MadeOfSport    schedule 25.03.2014    source источник


Ответы (1)


Моя интуиция подсказывает, что вы должны изменить базу данных, чтобы вместо этого у вас было отношение habtm.

Итак, ваши таблицы должны выглядеть так:

Products (id, title)
ProductCategories (product_id, category_id)
Categories (id, title)

Таким образом, продукт может относиться ко многим категориям.

Затем вы можете найти в своей таблице продукты, принадлежащие к категории с идентификатором = 1 и категории с идентификатором = 3, выполнив следующий запрос:

Запрос MySQL

SELECT Products.id, Products.title 
FROM Products
WHERE 
Products.id IN 
(
   SELECT c1.product_id 
   FROM ProductCategories AS c1 
     INNER JOIN ProductCategories AS c2
     ON c1.product_id = c2.product_id
   WHERE c1.category_id = 1 AND c2.category_id = 3
);
person Jens Stigaard    schedule 27.03.2014
comment
хорошо - выглядит хорошо. На данный момент у меня есть максимум 5 category_id для соответствия, поэтому я расширил ваше предложение и получил 5 внутренних объединений. Но что произойдет, если вы хотите масштабировать это и иметь 25 идентификаторов категорий, которые вы хотите сопоставить. - person MadeOfSport; 01.04.2014
comment
Да, я понимаю вашу проблему, и я думал так же, но пока у меня нет умного решения для этого. В CakePHP вы, возможно, могли бы сделать некоторую конкатенацию строки запроса для всех категорий.. Например foreach($categories as $category){ $query.= $inner_join_for_this_category; } $запрос; // Теперь содержит внутренние соединения для всех - person Jens Stigaard; 02.04.2014