Доброй ночи. Вот уже третью ночь не могу спать нормально и мучает меня одна задача, которую я придумал сам для себя. Введение: функционал как на сайте http://ogoloda.li/search, а именно мы выбираем список продуктов которые у нас есть и нам отображаются рецепты. Я не знаю как конкретно реализовано на данном сайте эта функция и никакого отношения не имею к этому ресурсу. Условия: 1. нету ajax 2. для получения рецептов в базу можно послать только 1 запрос 3. создание временных таблиц нежелательно 4. Структура таблиц может быть любой Как я вижу данную структуру (у вас может быть своя): Таблица 1 - таблица с ингредиентами Таблица 2 - таблица с рецептами Таблица 3 - связывающая таблица P.S. Запрос я так и не придумал и не факт что такой запрос можно составить, но что-то мне подсказывает, что решение есть у этой задачи
А что тут сложного? С JavaScript-получается более изящно, тем-более он не мешает никак серверным проверкам. Просто у данного ресурса, неудачно реализован "js-контроллер"-обработчик запросов от сервера, после получения ответа он обновит указанные элементы, в той последовательности в которой отдал сервер, после обработки запроса. На заказ такое дорого, но если хотите качества и баланса, стоит заказать 1 раз и забыть о проблемах. Задача тут одна. Таблица со всеми ингредиентами, рецептами, порциями и пропорциями, временем и готовкой (это должно быть расписано). Уже был подобный вопрос: http://php.ru/forum/viewtopic.php?f=13&t=45180&p=360713
Это задача не для коммерции и не для какого то проекта. Вы не поняли задачи, как это реализовать с помощью js, двух и более запросов это я все могу, меня просто интересует возможно ли получить результат с помощью одного sql запроса и что бы это не было кастылем Добавлено спустя 1 минуту 27 секунд: Задача больше теоретическая, чем практическая
одна таблица? Верно не совсем корретно понял ты суть кулинарного калькулятора. Это не просто сборник рецептов
С одной таблицей я вообще не представляю решения Добавлено спустя 1 минуту 49 секунд: Ну или жуткий костыль
Именно. Бред. Можно и с помощью одного запроса выбрать кучу данных из кучи таблиц. Джоины, подзапросы. Можно и без JS все это сделать. Но вопрос - нужно ли? Как раз выпилить JS тут проще простого. Отсылаем запрос не AJAX-ом, а в форме, после чего ответ, который AJAX вернул бы в страницу, дописываем к содержимому возвращаемой страницы и перезагружаем таковую(укажите экшон на нее же, само рефрешнется). И все. Отдали список продуктов, получили список рецептов. Вот база посложнее. Хитровыбоенные м-к-м связи нужны, пожалуй. Так с наскоку не одолеть прям..
Именно этот запрос меня и интересует, что после этого запроса я получил список рецептов, которые я могу приготовить из своих ингридиентов. ды как отправить запрос из html в php, а из php в MySQL - это не проблема и даже рассматривать не надо Дык и я вот уже, получается, 5 день думаю, как же это сделать, техническая реализация не так важна, как просто придумать алгоритм)
Две таблицы: рецепты и ингридиенты_рецепта. Ну или три: рецепты, ингридиенты, ингридиенты_рецепта. На твой вкус! Есть готовые примеры: http://stackoverflow.com/questions/11066631/sqlite-find-rec ... ngredients http://stackoverflow.com/questions/11658700/sql-query-for-r ... ients?rq=1
Уже интересно, почти так же как мне подсказали на соседнем форуме: Таблицы рецепты - recipe[id,Name,Description], ингридиенты ingredient[id,Name,Description], связь links[id,rId,iId] ключики тривиальны и неинтересны пришел набор ингридиентов в виде массива ID шек (таблица ingredient, получается, не нужна ) величиной , к примеру, 5 штук. Код (Text): select * from recipe as r join link as l1 on r.id=l1.rId join link as l2 on r.id=l2.rId join link as l3 on r.id=l3.rId join link as l4 on r.id=l4.rId join link as l5 on r.id=l5.rId where l1.iId=:ID1 and l2.iId=:ID2 and l3.iId=:ID3 and l4.iId=:ID4 and l5.iId=:ID5 сколько ингридиентов, столько и джойнов Но мне кажется есть еще красивее способ, но не факт
А так: таблица с ингредиентами - ingredients с полями id, title таблица с рецептами - recepts с полями id, title_recept связывающая таблица - conn с полями ingr, rec Код (Text): SELECT ingredients.title, recepts.title_recept FROM recepts INNER JOIN conn ON recepts.id = conn.rec INNER JOIN ingredients ON ingredients.id = conn.ingr WHERE ingredients.id = 1 OR ingredients.id = 4 Если 1 ингредиент существует в рецепте, то рецепт выводится. Если существуют 2 ингредиента, то выводятся две записи, например Код (Text): title title_recept Соль Лаваш армянский без дрожжей Мука Лаваш армянский без дрожжей Далее отсортировать в PHP. Например, если выбрана только соль, то ничего не выводить. В запросе меняется нижняя строка, добавляются "OR ingredients.id = 5" и т.п.
ИСандро, ошибка в том, что требуется найти по "И". рецепт должен содержать все перечисленные составляющие. Добавлено спустя 57 секунд: КиберЧегототам, ты был бы молодец, если бы подготовил исходные данные над которыми можно поработать. помещаешь на http://sqlfiddle.com/ а мы тебе даем свои красивые запросы.
artoodetoo, где такое требование? По ссылке на оголода.ли рецепт находится уже по одному продукту. Добавлено спустя 2 минуты 43 секунды: Если я ищу рецепты с мукой, не важно, будет там соль или сахар, то не нужно "И".
Блин, и правда! Тупой сайт ))) При таком раскладе решается через ... WHERE ingridient_id IN (3,5,25) вообще не паримся Добавлено спустя 1 минуту 46 секунд: Я то после беглого просмотра думал что есть у нас три корочки хлеба, одно яйцо и майонез и мы ищем как это максимально использовать. Бл* всё оказалось тупо
совершенно верно Сейчас подготовлю, структуру возьму из своего первого сообщения Добавлено спустя 2 минуты 24 секунды: не-не-не, не все так просто, нужно "...найти по "И". рецепт должен содержать все перечисленные составляющие"
Ну ок. Если у кого-то есть перец Чили вместо обычного перца, или вообще его нет, то простой рецепт с обычным перцем ему уже не найти. Разве что оголодавший пофантазирует "а если бы у меня был перец, то.. сделаем такой запрос". Мне кажется, нужно ещё задать приоритеты, какие продукты главные, а какие вспомогательные.
Это уже отдельная история, так называемые опциональные ингредиенты, типо "перец можно добавить, но не обязательно". В данной задаче это не нужно Добавлено спустя 8 минут 56 секунд: http://sqlfiddle.com/#!2/8f274 накидал структуру и забил тестовыми данными, для экспирементов
В идеальной системе была бы выдача по релевантности: от самых подходящих к менее подходящим. Тогда допустимо было бы неполное совпадение и совпадение в опциональных ингридиентах. На сайте же выдается хрен пойми что. Ищет, судя по всему, по "ИЛИ", а почему некоторые рецепты объявляет "полным совпадением" непонятно. Там может оказаться одно совпадение из трех -- так же как и в расширенном списке.
Код (Text): select * from recipe as r join link as l1 on r.id=l1.rId join link as l2 on r.id=l2.rId join link as l3 on r.id=l3.rId join link as l4 on r.id=l4.rId join link as l5 on r.id=l5.rId where l1.iId=:ID1 and l2.iId=:ID2 and l3.iId=:ID3 and l4.iId=:ID4 and l5.iId=:ID5 потестил метод, не совсем работает правильно
адаптация одного из рецептов со stackoverflow: http://sqlfiddle.com/#!2/8f274/26 Код (Text): select ri.Recepte_id from Ingredient_Recepte as ri left join ( select 4 as Ingredient_id union all select 5 ) as search on ri.Ingredient_id = search.Ingredient_id group by ri.Recepte_id having count(search.Ingredient_id) = 2 фишка в том, что мы с помощью "union all" создаем таблицу искомых ингридиентов. затем с помощью группировки и count() находим те рецепты, куда они вошли все. можно адаптировать для "релевантного поиска": вместо having делаем сортировку order by count(search.Ingredient_id) desc тыц
Сейчас попробовал подставить ингредиенты с id 2 и 3, что соответствует глазунье, а запрос так же выдал Омлет, хотя у нас не хватает молока Код (Text): select * from Ingredient_Recepte as ri left join ( select 2 as Ingredient_id union all select 3 ) as search on ri.Ingredient_id = search.Ingredient_id group by ri.Recepte_id having count(search.Ingredient_id) = 2 Может с запросом ошибся?
кажется мы говорим о разном. мой запрос выдает все рецепты, в которых есть все упомянутые составляющие. не "равен", а "включает в себя всё это". так что ответ правильный. а ты о чем? ------------------------------------------- вариант с IN() без джойна http://sqlfiddle.com/#!2/8f274/40 Код (Text): select ri.Recepte_id, count(*) as cnt from Ingredient_Recepte as ri where ri.Ingredient_id in (1,2,3) group by ri.Recepte_id having count(*) = 3
результат запроса должен показать мне список рецептов, которые я могу приготовить из продуктов которые уже имеются
Задача решена, кому интересно ответ - http://sqlfiddle.com/#!2/d4907/36 О таком алгоритме думал, но из-за плохого знания синтаксиса SQL думал что нельзя так сделать