PHP MySQL поиск рецептов на основе того, какие ингредиенты предоставляются - PullRequest
4 голосов
/ 02 сентября 2011

Скажем, у меня есть база данных рецептов, и я хочу искать их по тем ингредиентам, которые у меня есть.

Там должно быть 3 таблицы:

Рецепты (рид, имя),
Ингредиенты (iid, iname),
Отношения (рид, иид)

Далее, давайте представим, что у меня есть рецепт «тоста» и рецепт «пудинга с хлебом и маслом» - в тосте 2 ингредиента (хлеб с маслом) - в пудинге может быть хлеб с маслом, а также мука, яйца и вода - Всего 5.

Моя проблема в том, чтобы структурировать SQL-запрос на основе того, какие ингредиенты предоставляются в поиске. Если я отправлю 3 ингредиента в моем поиске - хлеб, масло и яйца - тогда (из 2 обсуждаемых рецептов) будет получен только один результат - тост! - потому что не хватает ингредиентов для приготовления пудинга!

Так как же на самом деле выглядит такой sql-запрос? Я все перепробовал, все погуглил, и теперь мой мозг уже не может с этим справиться.

Ответы [ 4 ]

1 голос
/ 02 сентября 2011

Не знаю, является ли это лучшим способом, но для приведенного вами примера это сработает:

SELECT
    *
FROM
    recipes
WHERE
    rid NOT IN (
        /* exclude all recipes with other ingredients */
        SELECT rid FROM relationship WHERE iid NOT IN (1, 2, 4)
    )

Извините за мой английский =)

Редактировать: ингредиенты 'Идентификаторы в том же порядке, что и в вашем вопросе, поэтому 1 - это хлеб, 2 - масло, 4 - яйца:

"iid"; "iname" "1"; "Хлеб" "2""Масло" "3"; "Мука" "4"; "Яйца" "5"; "Вода"

0 голосов
/ 02 сентября 2011

В моем ответе предполагается, что вы используете PDO, но вы изменяете свои потребности, если используете базовые вызовы mysql или mysqli:

$ingredient1 = $_POST['ingredient1'];
$ingredient2 = $_POST['ingredient2'];
$ingredient3 = $_POST['ingredient3'];

$sql = '
SELECT
 c.rid,
 c.rname
FROM ingredients a
JOIN relationship b ON (a.iid = b.iid)
JOIN recipes c ON (b.rid = c.rid)
WHERE
     (a.iname LIKE ? AND a.iname LIKE ? AND a.iname LIKE ?)
';

$stmt = $db->prepare($sql)
$stmt->execute(array('%'.$ingredient1.'%', '%'.$ingredient2.'%', '%'.$ingredient3.'%'));

Мой ответ предполагает, что, конечно, ваше утверждение всегда будет включать три рецепта, и вы используете переменные записи, но их также можно изменить, чтобы учесть изменчивость. Преимущества этого типа запроса по сравнению с другими данными в том, что вам не нужно использовать подзапросы, которые традиционно менее эффективны.

редактировать

забыл добавить символы '%' в значения массива. Это будет соответствовать любому названию ингредиента в соответствующей таблице. Если оно должно совпадать, просто удалите символы «LIKE» и «%» и поместите «=?».

0 голосов
/ 02 сентября 2011

Предположим, что "идентификаторы" содержат идентификаторы для поиска ингредиентов.

SELECT *
FROM Recipes
WHREE rid NOT IN (SELECT DISTINCT rid FROM Relationship WHERE iid NOT IN (ids))
0 голосов
/ 02 сентября 2011

Предполагая, что список iids задан (1,2,3), вы можете попробовать выбрать все из relationship, где iid находится в (1,2,3), а rid находится в (выбор rids в relationship с количеством <= количество <code>iids в списке)

...