[php][/php]
Dobry wieczór,
Jestem w trakcie pisania pracy dyplomowej i napotkałem problem dot. wyświetlania przepisów na podstawie wcześniej zaznaczonych produktów z formularza.
ZAMYSŁ:
Chcę stworzyć kwerendę, która będzie aktywowała się w momencie spełnienia warunku:
a) wszystkie składniki podane w formularzu muszą być zawarte w przepisie w przeciwnym wypadku przepis/y nie zostanie wyświetlony.
Kieruję pytanie do was jak muszę przerobić swoją kwerendę aby takowa kwerenda miała byt na mojej stronie?
Dla entuzjastów wysyłam plik .SQL ze strukturą bazy danych.
https://pastebin.pl/view/be6ecf46
Z góry dziękuję za każdą pomoc
może pokażesz jak to teraz robisz ?
mam utworzone takie zapytanie:
SELECT `przepisy`.*, `przepisy_skladniki`.`Przepisy_ID`, `przepisy_skladniki`.`Skladniki_ID`, `skladniki`.`Produkt` FROM `przepisy` LEFT JOIN `przepisy_skladniki` ON `przepisy_skladniki`.`Przepisy_ID` = `przepisy`.`ID` LEFT JOIN `skladniki` ON `przepisy_skladniki`.`Skladniki_ID` = `skladniki`.`ID`
WHERE `przepisy_skladniki`.`Skladniki_ID` = 209 or `przepisy_skladniki`.`Skladniki_ID` = 258 or `przepisy_skladniki`.`Skladniki_ID` = 229 or `przepisy_skladniki`.`Skladniki_ID` = 109
Co da taki oto rezultat:
Sernik staropolski, placki ziemniaczane oraz lemoniada
ID 209 - MIĘTA
ID 258 - Cukier
ID 229 - Olej sezamowy
ID 109 - Mango
Przykład:
Sernik staropolski:
Tego przepisu nie powinno w ogóle wyświetlić ponieważ brakuje wszystkich przepisów z samego Cukru nie zrobimy sernika
Liczby 209/258/229/109 zostały wpisane na sztywno, efekt finalny bedzie taki ze zostaną one pobrane z formularza i wstawione do kwerendy, na razie chce tylko sprawdzić czy to fizycznie działa.
Może nie odpowiem wprost na Twoje pytanie, ale warto popatrzeć na to zagadnienie z punktu widzenia kombinatoryki a właściwie na kombinację bez powtórzeń. Zakładając, że do przepisu potrzeba min. 2 składniki z liczby podanych to mamy takie zależności:
- dla wybranych 4 składników będziemy mieli 6 potencjalnych przepisów 2-składnikowych, 4 3-składnikowe, 1 1-składnikowy co daje 11 zbiorów składników do zapytania.
- odpowiednio dla 5 wybranych składników otrzymamy już liczbę 25 zbiorów składników do zapytania,
- dla 6 - 57 itd.
Każda kombinacja bez powtórzeń zbiorów składników musi być zawarta w zapytaniu, aby zapytanie było kompletne i prawdziwe.
Może jest jakiś sposób na takie zapytanie uniwersalne, ja go nie znam i nie wyobrażam go sobie. Podszedł bym do tego zagadnienia w inny sposób.
No nie wiem ja stworzyłem takie zapytanie.
o pobieranie danych z formularza się nie martwie bo jest to robione za pomocą formularza i kazda inkrementacja pętli spowoduje ze ID skladnika zostanie zmienione na inne.
Problem w tym, że nawet gdy nie podam wszystkich składnikow to mi się ten przepis wyświetli nie wiem jak to zrobić, a wszystkie fora jak na razie mnie zawiodły. Nie wiem czy jest to w ogóle wykonalne pisząc stronkę w środowisku bootstrap. Wiem, że wordpress ma wbudowany plugin, który umozliwia bezposrednie filtrowanie produktów, a jak to wyglada w bootstrapie nie wiem.
Formularz nie ma tu nic do rzeczy. Twoja aplikacja działa tak, że użytkownik wybiera ileś tam składników z formularza, załóżmy że wybrał mleko (value 200), cukier (value 210) i mąkę (value 220). Te value wysyłasz z formularza. I z tych składników wyszukujesz przepisy. Problem jest w tym, że aby sprawdzić wszystkie kombinacje składników z założeniem, że min muszą być 2 składniki, musisz utworzyć takie zestawy składników:
przepis 1. 200, 210, 220
przepis 2. 200, 210
przepis 3. 200, 220
przepis 4. 210, 220
I musisz tak zrobić, bo nie znasz wszystkich przepisów i ich składników wprowadz0nych do bazy i może być przepis oparty tylko na mące i mleku, albo mące i jajkach.
Takie zestawy produktów trzeba sprawdzić w warunku WHERE zapytania. Problem jest w tym, że przy wybraniu w formularzu 6,8,10 i więcej produktów ze wzoru na kombinacje bez powtórzeń tych zestawów składników będzie taka ilość, że nie ma mowy żeby skonstruować takie zapytanie. Tak jak chcesz to zrobić musisz sprawdzić wszystkie kombinacje przesłanych przez formularz produktów. Teraz Twoje zapytanie zawsze zwróci przepis z jednym lub dwoma produktami, bo tak to zapytanie działa.
Osobiście zrobił bym to na odwrót. W pętli, z każdego przepisu pobrał bym składniki i sprawdził czy array_diff zwraca 0 z tablicą przesłaną z formularza. Jeśli tak, to znalazł przepis bo jego wszystkie składniki mieszczą się w przesłanych składnikach, jak większa od zera to przepis z tych składników jest niekompletny. I tak przez wszstkie przepisy, pobieram sobie id tych przepisów co array_diff zwraca 0, a później to już bajka. Ale nie jestem wyrocznią w sql-u, to tylko moje zdanie.
To by miało sens bo prawdę mówiąc już zaczynam powoli tracić cierpliwość i nie wiedziałem jak rozwiązać ten problem.
Czy mógłbym prosić Pana o szersze wytłumaczenie, nigdy nie korzystałem z funkcji array_diff() i nie mam zbytnio pomysłu jak ją zaimplementować do swojego skryptu.
Mogę prosić o nakierowanie?
Byłbym ogromnie wdzięczny
<http://december.com/html/4/element/form.html name="add_name" id="add_name" action="" method="get"> <http://december.com/html/4/element/div.html class="row"> <http://december.com/html/4/element/div.html class="col-lg-12 mt-4 mt-lg-0"> <http://december.com/html/4/element/div.html class="tab-pane"> <http://december.com/html/4/element/div.html class="row"> <http://december.com/html/4/element/div.html class="col-lg-12 details order-2 order-lg-1"> <http://december.com/html/4/element/table.html style="width:100%"> <http://december.com/html/4/element/tr.html> <http://december.com/html/4/element/th.html style="text-align: center;"><http://december.com/html/4/element/h3.html>Podaj składniki</http://december.com/html/4/element/h3.html></http://december.com/html/4/element/th.html> <http://december.com/html/4/element/th.html style="text-align: center;"><http://december.com/html/4/element/h3.html>Znalezione przepisy</http://december.com/html/4/element/h3.html></http://december.com/html/4/element/th.html> </http://december.com/html/4/element/tr.html> </http://december.com/html/4/element/table.html> <!-- --> FORMULARZ ZE SKŁADNIKAMI <http://december.com/html/4/element/div.html class='form-group skladniki-list'> <?php if(isset($_SESSION['komunikat'])){ // WYŚWIETLA KOMUNIKAT O POMYSLNEJ REJESTRACJI/LOGOWANIU echo($_SESSION['komunikat']); unset($_SESSION['komunikat']); } ?> <http://december.com/html/4/element/div.html class='input-group'> <http://december.com/html/4/element/div.html class="col-lg-6 mt-4 mt-lg-0"> <http://december.com/html/4/element/div.html class="table-responsive"> <http://december.com/html/4/element/table.html class="table table-bordered" id="dynamic_field" style="border"> <http://december.com/html/4/element/td.html style="border: none;"> <?php include 'baza.php'; $skladniki_query = mysqli_query($connection, "SELECT * FROM `skladniki`"); $skladniki_rows = mysqli_num_rows($skladniki_query); if (mysqli_num_rows($skladniki_query) > 0) { echo"<http://december.com/html/4/element/select.html name='skladnik[]' class='selectpicker skladnik' data-live-search='true' title='Wybierz składnik' style='height: 200% !important ;'>"; while($skladniki_row = mysqli_fetch_assoc($skladniki_query)) { echo "<http://december.com/html/4/element/option.html value=" . $skladniki_row['ID'] .">" . $skladniki_row['Produkt'] . "</http://december.com/html/4/element/option.html>"; } echo "</http://december.com/html/4/element/select.html></http://december.com/html/4/element/td.html>"; } echo" <http://december.com/html/4/element/td.html style='border:none;'><http://december.com/html/4/element/button.html type='button' name='add' id='add' class='btn btn-outline-warning' style='line-height:1;'> Kolejny składnik</http://december.com/html/4/element/button.html></http://december.com/html/4/element/td.html> </http://december.com/html/4/element/tr.html>"; ?> </http://december.com/html/4/element/table.html> <http://december.com/html/4/element/input.html type="submit" class="btn btn-outline-warning" value="Wyszukaj" name="wyszukaj"> </http://december.com/html/4/element/div.html> </http://december.com/html/4/element/form.html>
SKRYPT ODPOWIEDZIALNY ZA WYŚWIETLANIE PRZEPISU/ÓW NA STRONIE
<?php http://www.php.net/error_reporting(-1); if (http://www.php.net/isset($_GET['wyszukaj'])) { //wywoływanie funkcji wyszukaj $liczba_skladnikow = http://www.php.net/count($_GET["skladnik"]); // wyciaganie informacji na temat ilosci wprowadzonych skladników if($liczba_skladnikow > 1) { for($i=0; $i<$liczba_skladnikow; $i++) { $skladnik = $_GET["skladnik"][$i]; /*echo "<BR></br> <br>"; echo "SELECT `przepisy`.*, `przepisy_skladniki`.`Przepisy_ID`, `przepisy_skladniki`.`Skladniki_ID`, `skladniki`.`Produkt` FROM `przepisy` LEFT JOIN `przepisy_skladniki` ON `przepisy_skladniki`.`Przepisy_ID` = `przepisy`.`ID` LEFT JOIN `skladniki` ON `przepisy_skladniki`.`Skladniki_ID` = `skladniki`.`ID` WHERE `przepisy`.`ID` = `przepisy_skladniki`.`Przepisy_ID` AND `przepisy_skladniki`.`Skladniki_ID` = ".mysqli_real_escape_string($connection, $_GET["skladnik"][$i])."";*/ $zapytanie = mysqli_query($connection, "SELECT `przepisy`.*, `przepisy_skladniki`.`Przepisy_ID`, `przepisy_skladniki`.`Skladniki_ID`, `skladniki`.`Produkt` FROM `przepisy` LEFT JOIN `przepisy_skladniki` ON `przepisy_skladniki`.`Przepisy_ID` = `przepisy`.`ID` LEFT JOIN `skladniki` ON `przepisy_skladniki`.`Skladniki_ID` = `skladniki`.`ID` WHERE `przepisy`.`ID` = `przepisy_skladniki`.`Przepisy_ID` AND `przepisy_skladniki`.`Skladniki_ID` = ".mysqli_real_escape_string($connection, $_GET["skladnik"][$i])." "); $zapytanie_rows = mysqli_num_rows($zapytanie); while($zapytanie_rows = mysqli_fetch_assoc($zapytanie)) { http://www.php.net/echo"<div class='about-img'> <a href='przepis.php?ID= ".$zapytanie_rows['ID']."&nazwa= ".$zapytanie_rows['Nazwa']."'> ".$zapytanie_rows['Nazwa']." </a> ".$zapytanie_rows['Produkt']." <img src='".$zapytanie_rows['obrazek']."' alt='' style='max-width: 100%; border: 4px solid rgba(255, 255, 255, 0.2); position: relative;'> </div>"; } } } } ?>
Jeśli wybiorę składniki: mąka, cukier, woda, to:
1. powinienem otrzymać przepisy, które zawierają dokładnie te składniki, ale mogą zawierać inne,
2. powinienem otrzymać przepisy, które zawierają dokładnie te składniki i tylko te (dokładnie 3 składniki),
?
Czy jeszcze jakoś inaczej?
trueblue z opisu autora wynika, że z przesłanych składników trzeba zrobić kompletne potrawy, składników może być mniej w potrawie ale nie więcej i nie inne niż przesłane z formularza. Tak ja to rozumiem.
Po wprowadzeniu składników chcę aby wyświetliło mi do nich przepis bądź przepisy. Jeżeli przepis zawiera np 6 produktów od ID (1,2,3,4,5,6,7,8) a drugi 3 produkty o IDA (2,3,9)
Wprowadzę 10 składników
1,2,3,4,5,6,7,8,10,11,12 (brakuje ID 9)
To powinno wyświetlić Przepis nr 1 (bo zawiera wszystkie produkty)
Przepisu nr 2 nie wyświetli bo nie został wprowadzony składnik nr 9 do formularza.
SELECT id, IF(SUM(exist IS NULL), NULL, SUM(exist)) AS total FROM( SELECT p.id,IF(ps.skladniki_id IN(1,3,4)>0,1,NULL) AS exist FROM przepisy AS p INNER JOIN przepisy_skladniki AS ps ON ps.przepisy_id=p.id) AS tmp GROUP BY id HAVING total
haha trueblue, ubiegłeś mnie, bo tez wpadłem na ten pomyśl, sprawdziłem Twój, chodzi ok
Zmień:
IF(ps.skladniki_id IN(1,3,4)>0,1,NULL)
IF(ps.skladniki_id IN(1,3,4),1,NULL)
SELECT id, IF(SUM(exist IS NULL), NULL, SUM(exist)) AS total FROM( SELECT p.id,IF(ps.skladniki_id IN(1,3,4)>0,1,NULL) AS exist FROM przepisy AS p INNER JOIN przepisy_skladniki AS ps ON ps.przepisy_id=p.id) AS tmp GROUP BY id HAVING total
No to dodaj je do zapytania: https://www.php.net/manual/en/function.implode.php
Pętla po składnikach nie jest potrzebna.
Udało się to co chciałem uczynić.
W pętli która pobiera dane do tablicy wystarczyło dopisać:
$zmienna = implode(",", $tablica);
następnie odnieść się z tą zmienną do kwerendy. Wszystko działa jak należy dziękuję za pomoc
Na marginesie chciałem dodać, że gdy wyskoczyłem ze swoim pomysłem to promotor był bardzo zaskoczony, że zdecydowałem się podjęcia napisania takiej kwerendy, która będzie w pełni zautomatyzowana.
@trueblue czy mogę prosić o szersze wytłumaczenie znaczenia napisanej przez Ciebie kwerendy? Wiem, że p ps itd. są to wskażniki a je się uzywa tylko po to aby nie pisać pełnych nazw tablic.
Napewno warto ten kod zamieścić w mojej dokumentacji i chcę szerzej go opisać./
SELECT *, IF(SUM(exist IS NULL), NULL, SUM(exist)) AS total FROM( SELECT p.Nazwa, p.obrazek, p.id,IF(ps.skladniki_id IN('".$dane."'),1,NULL)AS exist FROM przepisy AS p INNER JOIN przepisy_skladniki AS ps ON ps.przepisy_id=p.id) AS tmp GROUP BY id HAVING total"; $zapytanie = mysqli_query($connection,"SELECT *, IF(SUM(exist IS NULL), NULL, SUM(exist)) AS total FROM( SELECT p.Nazwa, p.obrazek, p.id,IF(ps.skladniki_id IN(".$dane."),1,NULL)AS exist FROM przepisy AS p INNER JOIN przepisy_skladniki AS ps ON ps.przepisy_id=p.id) AS tmp GROUP BY id HAVING total
Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)