Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Kwerenda wyświetlająca przepisy na podstawie zaznaczonych wcześniej do niej produktów.
adus97
post 30.11.2020, 21:26:45
Post #1





Grupa: Zarejestrowani
Postów: 20
Pomógł: 0
Dołączył: 3.11.2020

Ostrzeżenie: (0%)
-----


[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 biggrin.gif
Go to the top of the page
+Quote Post
gitbejbe
post 1.12.2020, 07:10:18
Post #2





Grupa: Zarejestrowani
Postów: 515
Pomógł: 63
Dołączył: 27.08.2012

Ostrzeżenie: (0%)
-----


może pokażesz jak to teraz robisz ?
Go to the top of the page
+Quote Post
adus97
post 1.12.2020, 17:22:37
Post #3





Grupa: Zarejestrowani
Postów: 20
Pomógł: 0
Dołączył: 3.11.2020

Ostrzeżenie: (0%)
-----


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 smile.gif

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.
Go to the top of the page
+Quote Post
gino
post 2.12.2020, 08:56:11
Post #4





Grupa: Zarejestrowani
Postów: 319
Pomógł: 52
Dołączył: 18.02.2008

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
adus97
post 2.12.2020, 16:18:52
Post #5





Grupa: Zarejestrowani
Postów: 20
Pomógł: 0
Dołączył: 3.11.2020

Ostrzeżenie: (0%)
-----


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.



Go to the top of the page
+Quote Post
gino
post 2.12.2020, 17:26:57
Post #6





Grupa: Zarejestrowani
Postów: 319
Pomógł: 52
Dołączył: 18.02.2008

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
adus97
post 2.12.2020, 19:23:53
Post #7





Grupa: Zarejestrowani
Postów: 20
Pomógł: 0
Dołączył: 3.11.2020

Ostrzeżenie: (0%)
-----


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

  1. <form name="add_name" id="add_name" action="" method="get">
  2. <div class="row">
  3.  
  4. <div class="col-lg-12 mt-4 mt-lg-0">
  5.  
  6.  
  7. <div class="tab-pane">
  8. <div class="row">
  9. <div class="col-lg-12 details order-2 order-lg-1">
  10. <table style="width:100%">
  11. <tr>
  12. <th style="text-align: center;"><h3>Podaj składniki</h3></th>
  13. <th style="text-align: center;"><h3>Znalezione przepisy</h3></th>
  14. </tr>
  15. </table>
  16.  
  17.  
  18. <!-- --> FORMULARZ ZE SKŁADNIKAMI
  19. <div class='form-group skladniki-list'>
  20. <?php
  21. if(isset($_SESSION['komunikat'])){ // WYŚWIETLA KOMUNIKAT O POMYSLNEJ REJESTRACJI/LOGOWANIU
  22. echo($_SESSION['komunikat']);
  23. unset($_SESSION['komunikat']);
  24. }
  25. ?>
  26.  
  27. <div class='input-group'>
  28. <div class="col-lg-6 mt-4 mt-lg-0">
  29. <div class="table-responsive">
  30. <table class="table table-bordered" id="dynamic_field" style="border">
  31. <td style="border: none;">
  32. <?php
  33. include 'baza.php';
  34. $skladniki_query = mysqli_query($connection, "SELECT * FROM `skladniki`");
  35. $skladniki_rows = mysqli_num_rows($skladniki_query);
  36. if (mysqli_num_rows($skladniki_query) > 0) {
  37. echo"<select name='skladnik[]' class='selectpicker skladnik' data-live-search='true' title='Wybierz składnik' style='height: 200% !important ;'>";
  38. while($skladniki_row = mysqli_fetch_assoc($skladniki_query)) {
  39. echo "<option value=" . $skladniki_row['ID'] .">" . $skladniki_row['Produkt'] . "</option>";
  40. }
  41. echo "</select></td>";
  42. }
  43. echo"
  44.  
  45.  
  46. <td style='border:none;'><button type='button' name='add' id='add' class='btn btn-outline-warning' style='line-height:1;'>
  47. Kolejny składnik</button></td>
  48. </tr>";
  49. ?>
  50. </table>
  51. <input type="submit" class="btn btn-outline-warning" value="Wyszukaj" name="wyszukaj">
  52. </div>
  53. </form>



  1. <?php
  2. if (isset($_GET['wyszukaj'])) { //wywoływanie funkcji wyszukaj
  3. $liczba_skladnikow = count($_GET["skladnik"]); // wyciaganie informacji na temat ilosci wprowadzonych skladników
  4. if($liczba_skladnikow > 1)
  5. {
  6. for($i=0; $i<$liczba_skladnikow; $i++)
  7. {
  8. $skladnik = $_GET["skladnik"][$i];
  9. /*echo "<BR></br> <br>";
  10.   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])."";*/
  11. $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])." ");
  12. $zapytanie_rows = mysqli_num_rows($zapytanie);
  13. while($zapytanie_rows = mysqli_fetch_assoc($zapytanie)) {
  14. echo"<div class='about-img'>
  15. <a href='przepis.php?ID= ".$zapytanie_rows['ID']."&nazwa= ".$zapytanie_rows['Nazwa']."'> ".$zapytanie_rows['Nazwa']." </a>
  16. ".$zapytanie_rows['Produkt']."
  17. <img src='".$zapytanie_rows['obrazek']."' alt='' style='max-width: 100%;
  18. border: 4px solid rgba(255, 255, 255, 0.2);
  19. position: relative;'>
  20. </div>";
  21. }
  22.  
  23. }
  24. }
  25. }
  26. ?>
SKRYPT ODPOWIEDZIALNY ZA WYŚWIETLANIE PRZEPISU/ÓW NA STRONIE
Go to the top of the page
+Quote Post
trueblue
post 2.12.2020, 19:38:20
Post #8





Grupa: Zarejestrowani
Postów: 6 761
Pomógł: 1822
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


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?

Ten post edytował trueblue 2.12.2020, 19:38:36


--------------------
Go to the top of the page
+Quote Post
gino
post 2.12.2020, 19:49:41
Post #9





Grupa: Zarejestrowani
Postów: 319
Pomógł: 52
Dołączył: 18.02.2008

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
adus97
post 2.12.2020, 20:13:03
Post #10





Grupa: Zarejestrowani
Postów: 20
Pomógł: 0
Dołączył: 3.11.2020

Ostrzeżenie: (0%)
-----


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.


Go to the top of the page
+Quote Post
trueblue
post 3.12.2020, 11:42:23
Post #11





Grupa: Zarejestrowani
Postów: 6 761
Pomógł: 1822
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


  1. SELECT id, IF(SUM(exist IS NULL), NULL, SUM(exist)) AS total
  2. FROM(
  3. SELECT p.id,IF(ps.skladniki_id IN(1,3,4)>0,1,NULL) AS exist
  4. FROM przepisy AS p
  5. INNER JOIN przepisy_skladniki AS ps ON ps.przepisy_id=p.id) AS tmp
  6. GROUP BY id
  7. HAVING total


Sprawdź takie zapytanie. Wybiera tylko przepisy (bez składników), z wybranymi składnikami 1,3,4.

P.S. Warto nazywać tabelę według krotki, którą przechowują - tabela przechowująca przepisy, nazywa się od struktury (wiersza): przepis. Osobiście klucze główne i obce nazywam tak samo. Łatwiej wtedy połapać się przy pisaniu JOIN i WHERE. Czyli: przepis.id_przepis i klucz obcy przepis_skladnik.id_przepis.






--------------------
Go to the top of the page
+Quote Post
gino
post 3.12.2020, 12:06:21
Post #12





Grupa: Zarejestrowani
Postów: 319
Pomógł: 52
Dołączył: 18.02.2008

Ostrzeżenie: (0%)
-----


haha trueblue, ubiegłeś mnie, bo tez wpadłem na ten pomyśl, sprawdziłem Twój, chodzi ok
Go to the top of the page
+Quote Post
trueblue
post 3.12.2020, 14:50:50
Post #13





Grupa: Zarejestrowani
Postów: 6 761
Pomógł: 1822
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


Zmień:
  1. IF(ps.skladniki_id IN(1,3,4)>0,1,NULL)

na:
  1. IF(ps.skladniki_id IN(1,3,4),1,NULL)

czyli bez nierówności (to pozostałość po użyciu funkcji FIND_IN_SET).


--------------------
Go to the top of the page
+Quote Post
adus97
post 3.12.2020, 15:10:49
Post #14





Grupa: Zarejestrowani
Postów: 20
Pomógł: 0
Dołączył: 3.11.2020

Ostrzeżenie: (0%)
-----


Cytat(trueblue @ 3.12.2020, 11:42:23 ) *
  1. SELECT id, IF(SUM(exist IS NULL), NULL, SUM(exist)) AS total
  2. FROM(
  3. SELECT p.id,IF(ps.skladniki_id IN(1,3,4)>0,1,NULL) AS exist
  4. FROM przepisy AS p
  5. INNER JOIN przepisy_skladniki AS ps ON ps.przepisy_id=p.id) AS tmp
  6. GROUP BY id
  7. HAVING total


Sprawdź takie zapytanie. Wybiera tylko przepisy (bez składników), z wybranymi składnikami 1,3,4.

P.S. Warto nazywać tabelę według krotki, którą przechowują - tabela przechowująca przepisy, nazywa się od struktury (wiersza): przepis. Osobiście klucze główne i obce nazywam tak samo. Łatwiej wtedy połapać się przy pisaniu JOIN i WHERE. Czyli: przepis.id_przepis i klucz obcy przepis_skladnik.id_przepis.


Dziękuję, Pana zapytanie działa tak jak należy. Jeżeli zabraknie przynajmniej jednego składnika do określonego przepisu to go nie wyświetli.


Teraz natrafiłem na problem z zamieszczeniem zmiennych tablicowych do mojej kwerendy jak widzicie Państwo
$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(209,258,372, 264, 255, 195)>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");

Pogrubione wartości zostały wpisane na sztywno przez co bedzie tylko wyszukiwało dwa przepisy: Lemoniada oraz Chipsy serowe. Ta kwerenda powinna generować automatycznie rózne cyfry w zależności od tych wprowadzonych z formularza.

Go to the top of the page
+Quote Post
trueblue
post 3.12.2020, 15:19:01
Post #15





Grupa: Zarejestrowani
Postów: 6 761
Pomógł: 1822
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


No to dodaj je do zapytania: https://www.php.net/manual/en/function.implode.php
Pętla po składnikach nie jest potrzebna.


--------------------
Go to the top of the page
+Quote Post
adus97
post 4.12.2020, 00:48:56
Post #16





Grupa: Zarejestrowani
Postów: 20
Pomógł: 0
Dołączył: 3.11.2020

Ostrzeżenie: (0%)
-----


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 smile.gif

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ć./
  1. SELECT *, IF(SUM(exist IS NULL), NULL, SUM(exist)) AS total FROM( SELECT p.Nazwa, p.obrazek, p.id,IF(ps.skladniki_id
  2. 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";
  3. $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
  4. 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


A jeszcze jedno czy tą kwerendę można jeszcze bardziej urozmaicić w sensie gdy brakuje nam 1-2 składników to wyświetli przepis lecz zostanie zamieszczona informacja, że brakuje jeszcze określonych składników.
Jak zostanie mi czas to chciałbym coś takiego uwzględnić w swojej pracy dyplomowej, ale nie jest to już tak obowiązkowe.

Ten post edytował adus97 3.12.2020, 21:38:13
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 19.03.2024 - 04:08