За последние 24 часа нас посетили 32823 программиста и 1821 робот. Сейчас ищут 1428 программистов ...

Помогите решить задачу

Тема в разделе "MySQL", создана пользователем CyberPulse, 30 авг 2013.

  1. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    Доброй ночи. Вот уже третью ночь не могу спать нормально и мучает меня одна задача, которую я придумал сам для себя.

    Введение: функционал как на сайте http://ogoloda.li/search, а именно мы выбираем список продуктов которые у нас есть и нам отображаются рецепты. Я не знаю как конкретно реализовано на данном сайте эта функция и никакого отношения не имею к этому ресурсу.

    Условия:
    1. нету ajax
    2. для получения рецептов в базу можно послать только 1 запрос
    3. создание временных таблиц нежелательно
    4. Структура таблиц может быть любой

    Как я вижу данную структуру (у вас может быть своя):
    Таблица 1 - таблица с ингредиентами
    Таблица 2 - таблица с рецептами
    Таблица 3 - связывающая таблица

    P.S. Запрос я так и не придумал и не факт что такой запрос можно составить, но что-то мне подсказывает, что решение есть у этой задачи
     
  2. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Мб во фриланс, не?
     
  3. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    А что тут сложного?
    С JavaScript-получается более изящно, тем-более он не мешает никак серверным проверкам.
    Просто у данного ресурса, неудачно реализован "js-контроллер"-обработчик запросов от сервера, после получения ответа он обновит указанные элементы, в той последовательности в которой отдал сервер, после обработки запроса.

    На заказ такое дорого, но если хотите качества и баланса, стоит заказать 1 раз и забыть о проблемах.

    Задача тут одна.
    Таблица со всеми ингредиентами, рецептами, порциями и пропорциями, временем и готовкой (это должно быть расписано).

    Уже был подобный вопрос:
    http://php.ru/forum/viewtopic.php?f=13&t=45180&p=360713
     
  4. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    Это задача не для коммерции и не для какого то проекта.
    Вы не поняли задачи, как это реализовать с помощью js, двух и более запросов это я все могу, меня просто интересует возможно ли получить результат с помощью одного sql запроса и что бы это не было кастылем

    Добавлено спустя 1 минуту 27 секунд:
    Задача больше теоретическая, чем практическая
     
  5. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    одна таблица? :) Верно не совсем корретно понял ты суть кулинарного калькулятора. Это не просто сборник рецептов :)
     
  6. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    С одной таблицей я вообще не представляю решения

    Добавлено спустя 1 минуту 49 секунд:
    Ну или жуткий костыль
     
  7. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Именно. Бред.
    Можно и с помощью одного запроса выбрать кучу данных из кучи таблиц. Джоины, подзапросы. Можно и без JS все это сделать. Но вопрос - нужно ли?

    Как раз выпилить JS тут проще простого. Отсылаем запрос не AJAX-ом, а в форме, после чего ответ, который AJAX вернул бы в страницу, дописываем к содержимому возвращаемой страницы и перезагружаем таковую(укажите экшон на нее же, само рефрешнется). И все. Отдали список продуктов, получили список рецептов.

    Вот база посложнее. Хитровыбоенные м-к-м связи нужны, пожалуй. Так с наскоку не одолеть прям..
     
  8. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    Именно этот запрос меня и интересует, что после этого запроса я получил список рецептов, которые я могу приготовить из своих ингридиентов.

    ды как отправить запрос из html в php, а из php в MySQL - это не проблема и даже рассматривать не надо

    Дык и я вот уже, получается, 5 день думаю, как же это сделать, техническая реализация не так важна, как просто придумать алгоритм)
     
  9. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
  10. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    Уже интересно, почти так же как мне подсказали на соседнем форуме:
    Таблицы
    рецепты - recipe[id,Name,Description],
    ингридиенты ingredient[id,Name,Description],
    связь links[id,rId,iId]
    ключики тривиальны и неинтересны

    пришел набор ингридиентов в виде массива ID шек (таблица ingredient, получается, не нужна ;) ) величиной , к примеру, 5 штук.
    Код (Text):
    1. select * from recipe as r
    2.   join link as l1 on r.id=l1.rId
    3.   join link as l2 on r.id=l2.rId
    4.   join link as l3 on r.id=l3.rId
    5.   join link as l4 on r.id=l4.rId
    6.   join link as l5 on r.id=l5.rId
    7. where
    8.   l1.iId=:ID1
    9.  and l2.iId=:ID2
    10.  and l3.iId=:ID3
    11.  and l4.iId=:ID4
    12.  and l5.iId=:ID5
    сколько ингридиентов, столько и джойнов

    Но мне кажется есть еще красивее способ, но не факт :)
     
  11. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    есть красивее. в тех ссылках что я тебе дал :)
     
  12. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    А так:
    таблица с ингредиентами - ingredients с полями id, title
    таблица с рецептами - recepts с полями id, title_recept
    связывающая таблица - conn с полями ingr, rec
    Код (Text):
    1. SELECT
    2.   ingredients.title,
    3.   recepts.title_recept
    4. FROM recepts
    5.   INNER JOIN conn
    6.     ON recepts.id = conn.rec
    7.   INNER JOIN ingredients
    8.     ON ingredients.id = conn.ingr
    9. WHERE ingredients.id = 1 OR ingredients.id = 4
    Если 1 ингредиент существует в рецепте, то рецепт выводится.
    Если существуют 2 ингредиента, то выводятся две записи, например
    Код (Text):
    1. title    title_recept
    2. Соль     Лаваш армянский без дрожжей
    3. Мука     Лаваш армянский без дрожжей
    Далее отсортировать в PHP. Например, если выбрана только соль, то ничего не выводить.
    В запросе меняется нижняя строка, добавляются "OR ingredients.id = 5" и т.п.
     
  13. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    ИСандро, ошибка в том, что требуется найти по "И". рецепт должен содержать все перечисленные составляющие.

    Добавлено спустя 57 секунд:
    КиберЧегототам, ты был бы молодец, если бы подготовил исходные данные над которыми можно поработать.
    помещаешь на http://sqlfiddle.com/ а мы тебе даем свои красивые запросы.
     
  14. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    artoodetoo, где такое требование? По ссылке на оголода.ли рецепт находится уже по одному продукту.

    Добавлено спустя 2 минуты 43 секунды:
    Если я ищу рецепты с мукой, не важно, будет там соль или сахар, то не нужно "И".
     
  15. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Блин, и правда! Тупой сайт ))) При таком раскладе решается через ... WHERE ingridient_id IN (3,5,25)
    вообще не паримся

    Добавлено спустя 1 минуту 46 секунд:
    Я то после беглого просмотра думал что есть у нас три корочки хлеба, одно яйцо и майонез и мы ищем как это максимально использовать.
    Бл* :D всё оказалось тупо
     
  16. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    совершенно верно
    Сейчас подготовлю, структуру возьму из своего первого сообщения

    Добавлено спустя 2 минуты 24 секунды:
    не-не-не, не все так просто, нужно "...найти по "И". рецепт должен содержать все перечисленные составляющие"
     
  17. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Ну ок. Если у кого-то есть перец Чили вместо обычного перца, или вообще его нет, то простой рецепт с обычным перцем ему уже не найти. Разве что оголодавший пофантазирует "а если бы у меня был перец, то.. сделаем такой запрос".
    Мне кажется, нужно ещё задать приоритеты, какие продукты главные, а какие вспомогательные.
     
  18. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    Это уже отдельная история, так называемые опциональные ингредиенты, типо "перец можно добавить, но не обязательно". В данной задаче это не нужно

    Добавлено спустя 8 минут 56 секунд:
    http://sqlfiddle.com/#!2/8f274 накидал структуру и забил тестовыми данными, для экспирементов
     
  19. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    В идеальной системе была бы выдача по релевантности: от самых подходящих к менее подходящим. Тогда допустимо было бы неполное совпадение и совпадение в опциональных ингридиентах.

    На сайте же выдается хрен пойми что. Ищет, судя по всему, по "ИЛИ", а почему некоторые рецепты объявляет "полным совпадением" непонятно. Там может оказаться одно совпадение из трех -- так же как и в расширенном списке.
     
  20. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    Код (Text):
    1. select * from recipe as r
    2.   join link as l1 on r.id=l1.rId
    3.   join link as l2 on r.id=l2.rId
    4.   join link as l3 on r.id=l3.rId
    5.   join link as l4 on r.id=l4.rId
    6.   join link as l5 on r.id=l5.rId
    7. where
    8.   l1.iId=:ID1
    9.  and l2.iId=:ID2
    10.  and l3.iId=:ID3
    11.  and l4.iId=:ID4
    12.  and l5.iId=:ID5
    потестил метод, не совсем работает правильно
     
  21. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    адаптация одного из рецептов со stackoverflow:
    http://sqlfiddle.com/#!2/8f274/26
    Код (Text):
    1. select  ri.Recepte_id
    2. from    Ingredient_Recepte as ri
    3. left join
    4.         (
    5.         select  4 as Ingredient_id
    6.         union all
    7.         select  5
    8.         ) as search
    9. on      ri.Ingredient_id = search.Ingredient_id
    10. group by
    11.         ri.Recepte_id
    12. having  count(search.Ingredient_id) = 2
    фишка в том, что мы с помощью "union all" создаем таблицу искомых ингридиентов. затем с помощью группировки и count() находим те рецепты, куда они вошли все.

    можно адаптировать для "релевантного поиска": вместо having делаем сортировку
    order by count(search.Ingredient_id) desc
    тыц
     
  22. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    Сейчас попробовал подставить ингредиенты с id 2 и 3, что соответствует глазунье, а запрос так же выдал Омлет, хотя у нас не хватает молока
    Код (Text):
    1. select  *
    2. from    Ingredient_Recepte as ri
    3. left join
    4.         (
    5.         select  2 as Ingredient_id
    6.         union all
    7.         select  3
    8.         ) as search
    9. on      ri.Ingredient_id = search.Ingredient_id
    10. group by
    11.         ri.Recepte_id
    12. having  count(search.Ingredient_id) = 2
    Может с запросом ошибся?
     
  23. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    кажется мы говорим о разном. мой запрос выдает все рецепты, в которых есть все упомянутые составляющие. не "равен", а "включает в себя всё это". так что ответ правильный.

    а ты о чем?

    -------------------------------------------
    вариант с IN() без джойна
    http://sqlfiddle.com/#!2/8f274/40
    Код (Text):
    1. select  ri.Recepte_id, count(*) as cnt
    2. from    Ingredient_Recepte as ri
    3. where   ri.Ingredient_id in (1,2,3)
    4. group by ri.Recepte_id
    5. having  count(*) = 3
     
  24. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    результат запроса должен показать мне список рецептов, которые я могу приготовить из продуктов которые уже имеются
     
  25. CyberPulse

    CyberPulse Новичок

    С нами с:
    30 авг 2013
    Сообщения:
    16
    Симпатии:
    0
    Задача решена, кому интересно ответ - http://sqlfiddle.com/#!2/d4907/36
    О таком алгоритме думал, но из-за плохого знания синтаксиса SQL думал что нельзя так сделать