Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [MySQL][PHP] Wyszukiwanie przepisów po składnikach
d0m1n1k_
post
Post #1





Grupa: Zarejestrowani
Postów: 208
Pomógł: 3
Dołączył: 13.07.2009
Skąd: Tarnów

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


Witam,
szukam dobrego rozwiązania które pozwoliłoby mi na wyszukiwanie przepisów po podanych składnikach.
Ważne aby pokazywało tylko te przepisy które nie mają innych składników niż te które wprowadziłem w inpucie.

Struktura bazy danych:
(Tabela: kolumna1,...)
przepisy: id, nazwa
przepisy_skladniki: ps_id, ps_przepis, ps_skladnik

Na chwilę obecną zdołałem napisać następujące zapytania:
  1. select DISTINCT r.nazwa, r.id
  2. from
  3. przepisy r
  4. inner join przepisy_skladniki i
  5. on i.ps_przepis = r.id
  6. where i.ps_skladnik IN (15, 99)

Problem: Pokazuje przepisy które zawierają wymienione składniaki (15 i 99 to id składników o które zapytałem)

  1. select r.nazwa, r.id
  2. from
  3. przepisy r
  4. inner join przepisy_skladniki i
  5. on i.ps_przepis = r.id
  6. where i.ps_skladnik IN (15, 99)
  7. GROUP BY r.nazwa
  8. HAVING COUNT(*) = 2


Problem: Pokazuje ten przepis który ma te składniki ale i inne, a nie ten który ma tylko te wyniki.

Co robię nie tak?
Count(*) > 2?
Też nie działa poprawnie.
Bardzo proszę o pomysł, pomoc lub rozwiązanie za które po stokroć dziękuję już teraz!
Go to the top of the page
+Quote Post
2 Stron V   1 2 >  
Start new topic
Odpowiedzi (1 - 19)
trueblue
post
Post #2





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


Sprawdź czy jest ok.
  1. SELECT DISTINCT p.nazwa,p.id_przepis
  2. FROM przepis AS p,przepis_skladnik AS ps
  3. WHERE p.id_przepis=ps.id_przepis
  4. GROUP BY p.id_przepis
  5. HAVING SUM(IF(ps.id_skladnik IN(1,2),1,-1))=2
Go to the top of the page
+Quote Post
Pyton_000
post
Post #3





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Albo coś takiego:
http://stackoverflow.com/a/7505147/3732803
Go to the top of the page
+Quote Post
trueblue
post
Post #4





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


Pyton_000,
to zapytanie zwróci przepisy, które zawierają również składniki spoza wybranych.
Go to the top of the page
+Quote Post
Pyton_000
post
Post #5





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Nie powinno chyba że zdefiniuje warunek HAVING >= X
Go to the top of the page
+Quote Post
trueblue
post
Post #6





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


Nie powinno, ale zwróci:)
Spięcie tabel jest po id_przepis, więc jeśli przepis ma 5 składników, ale 2 z nich wybrane, to i tak zostanie wyselekcjonowany do puli wyników.
Go to the top of the page
+Quote Post
mmmmmmm
post
Post #7





Grupa: Zarejestrowani
Postów: 1 421
Pomógł: 310
Dołączył: 18.04.2012

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


trueblue
Twoje zapytanie rónież zwróci źle. Zakładając, że najważniejsze jest:
  1. HAVING SUM(IF(ps.id_skladnik IN(1,2),1,-1))=2

to dla ps.id_skladnik ={1,2,3,4} również zwróci 2 (IMG:style_emoticons/default/smile.gif)
dla ps.id_skladnik = {1,1} także zwróci 2
Go to the top of the page
+Quote Post
trueblue
post
Post #8





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


Cytat(mmmmmmm @ 3.09.2015, 12:58:53 ) *
trueblue
Twoje zapytanie rónież zwróci źle. Zakładając, że najważniejsze jest:
  1. HAVING SUM(IF(ps.id_skladnik IN(1,2),1,-1))=2

to dla ps.id_skladnik ={1,2,3,4} również zwróci 2 (IMG:style_emoticons/default/smile.gif)
dla ps.id_skladnik = {1,1} także zwróci 2

mmmmmmm,
Dla pierwszego przykładu zwróci 0 (+1,+1,-1,-1)
Dla drugiego, tak, masz rację. Choć wiadomo jakie powinno być założenie co do tabeli.

Ten post edytował trueblue 3.09.2015, 12:09:42
Go to the top of the page
+Quote Post
d0m1n1k_
post
Post #9





Grupa: Zarejestrowani
Postów: 208
Pomógł: 3
Dołączył: 13.07.2009
Skąd: Tarnów

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


trueblue nie wiem czy to moja wina przepisania czy zrozumienia, ale zapytanie:
  1. SELECT DISTINCT p.nazwa, p.id
  2. FROM przepisy AS p, przepisy_skladniki AS ps
  3. WHERE p.id = ps.ps_przepis
  4. GROUP BY p.id
  5. HAVING SUM(ID(ps.ps_id IN(1,2),1-1))=2


wyrzuca wynik w phpmyadmin: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))=2 LIMIT 0, 30' at line 5

Poza tym zastanawiam się, jeśli chciałbym podawać mniej lub więcej niż dwa składniki (np. w przedziale od 1 do 20) to jak powinienem do tego podjeść?
Czy może to wyglądać w ten sposób:

  1. $id_wszystkichskladnikow = $_POST['skladnik1'] . ", " . $_POST['skladnik2'] . ", " ... ", " . $_POST['skladnik20'];
  2. $suma_id = "20";
  3.  
  4. select r.nazwa, r.id
  5. from
  6. przepisy r
  7. inner join przepisy_skladniki i
  8. on i.ps_przepis = r.id
  9. where i.ps_skladnik IN (" . $id_wszystkichskladnikow . ")
  10. GROUP BY r.nazwa
  11. HAVING COUNT(*) = " . $suma_id . "
  12.  


Czy jestem na dobrym tropie? Czy nadal głęboko w lesie :-///

Ten post edytował d0m1n1k_ 3.09.2015, 14:15:51
Go to the top of the page
+Quote Post
trueblue
post
Post #10





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


  1. HAVING SUM(ID(ps.ps_id IN(1,2),1-1))=2

IF nie ID

Tyle ile id składników, takie porównanie z ilością.
Dla 4-ech byłoby:
  1. HAVING SUM(IF(ps.id_skladnik IN(1,2,5,10),1,-1))=4


Pamiętaj aby w tabeli przepisy_skladniki nie mieć przypisanego kilkukrotnie tego samego składnika do przepisu (powinien być indeks unikalny na dwóch polach).
Go to the top of the page
+Quote Post
d0m1n1k_
post
Post #11





Grupa: Zarejestrowani
Postów: 208
Pomógł: 3
Dołączył: 13.07.2009
Skąd: Tarnów

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


Z tym ID/IF to mój błąd przy wprowadzaniu zapytania na forum.
W phpMyAdmin było poprawnie (IF) i błąd wystąpił przy IF'ie ten który opisałem w poprzednim poście.
Czyli ostatnia linijka powinna wyglądać następująco?:
  1. HAVING SUM(IF(ps.id_skladnik IN(" . $id_wszystkichskladnikow . "),1,-1))=" . $suma_id . "


Dobrze to rozumiem?

Co do mysql i unikalności, mam to wykonać w następujący sposób?:

  1. ALTER TABLE przepisy_skladniki
  2. ADD UNIQUE KEY `unikalnoscskladnikow` (`ps_przepis`, `ps_skladnik`)


POPRAWKA!

Kod poprawiony:

HAVING SUM(IF(ps.ps_id IN(1,2),1,-1))=2

Takie szczegóły ;-)

Ale teraz wywala mi wynik zerowy dla zapytania 15,99 a powinno pokazać dwa przepisy :-///

Ten post edytował d0m1n1k_ 3.09.2015, 14:50:43
Go to the top of the page
+Quote Post
trueblue
post
Post #12





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


Pokaż zapytanie dla id 15 i 99.

Indeks ok, jeśli te pola to id przepisu i składnika.

Ten post edytował trueblue 3.09.2015, 14:53:15
Go to the top of the page
+Quote Post
d0m1n1k_
post
Post #13





Grupa: Zarejestrowani
Postów: 208
Pomógł: 3
Dołączył: 13.07.2009
Skąd: Tarnów

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


Na chwilę obecną sprawdzam statyczne zapytanie, bez zmiennych.

  1. SELECT DISTINCT p.nazwa, p.id
  2. FROM przepisy AS p, przepisy_skladniki AS ps
  3. WHERE p.id = ps.ps_przepis
  4. GROUP BY p.id
  5. HAVING SUM(IF(ps.ps_id IN(15, 99),1,-1))=2


Przypomnę układ tabel:
(Przepis) przepisy: id, nazwa
(Składniki) przepisy_skladniki: ps_id, ps_przepis, ps_skladnik
Go to the top of the page
+Quote Post
trueblue
post
Post #14





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


  1. SELECT DISTINCT p.nazwa, p.id
  2. FROM przepisy AS p, przepisy_skladniki AS ps
  3. WHERE p.id = ps.ps_przepis
  4. GROUP BY p.id
  5. HAVING SUM(IF(ps.ps_skladnik IN(15, 99),1,-1))=2


Pole ps_id w tabeli przepisy_skladniki nie jest potrzebne jeśli założyłeś indeks unikalny.
Go to the top of the page
+Quote Post
d0m1n1k_
post
Post #15





Grupa: Zarejestrowani
Postów: 208
Pomógł: 3
Dołączył: 13.07.2009
Skąd: Tarnów

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


Przeanalizowałem.
Mały błąd już teraz działa (IMG:style_emoticons/default/smile.gif)

  1. SELECT DISTINCT p.nazwa, p.id
  2. FROM przepisy AS p, przepisy_skladniki AS ps
  3. WHERE p.id = ps.ps_przepis
  4. GROUP BY p.id
  5. HAVING SUM(IF(ps.ps_skladnik IN(15, 99),1,-1))=2


W ostatniej linijce zamiast ps.ps_id wykorzystałem ps.ps_skladnik


Równo to zauważyliśmy ;-)
Ale za tyle pomocy Piwo Ci się należy! I po trój kroć klik pomógł!

Ale teeeeraz. Jak już sprawę podstawową mam załatwioną, to teraz zastanawiam się nad rozwinięciem.
Jak mógłbym zmodyfikować kod aby pokazywał mi przepisy które mają jeden lub dwa składniki więcej, sortowane po tej wartości od 1 do 10 składników dodatkowych.

Ten post edytował d0m1n1k_ 3.09.2015, 15:03:33
Go to the top of the page
+Quote Post
trueblue
post
Post #16





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


Zerknij, jeśli działa, to być może da się uprościć:
  1. SELECT DISTINCT p.nazwa, p.id, (SUM(IF(ps.ps_skladnik IN(15, 99),1,-1)) AS ilosc_podstawowa,SUM(IF(ps.ps_skladnik NOT IN(15, 99),1,-1))) AS ilosc_dodatkowa
  2. FROM przepisy AS p, przepisy_skladniki AS ps
  3. WHERE p.id = ps.ps_przepis
  4. GROUP BY p.id
  5. HAVING ilosc_podstawowa=2 AND ilosc_dodatkowa>=5
  6. ORDER BY ilosc_dodatkowa
Go to the top of the page
+Quote Post
d0m1n1k_
post
Post #17





Grupa: Zarejestrowani
Postów: 208
Pomógł: 3
Dołączył: 13.07.2009
Skąd: Tarnów

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


Niestety nie działa.
Error: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS ilosc_podstawowa,SUM(IF(ps.ps_skladnik NOT IN(15, 99),1,-1))) AS ilosc_dodatk' at line 1

Zaś po zmianie nawiasów dls ilosc_podstawowa i ilosc_dodatkowa, aby były osobnymi wartościami wywala mi pusty wynik.

  1. SELECT DISTINCT p.nazwa, p.id,
  2. (SUM(IF(ps.ps_skladnik IN(15, 99),1,-1))) AS ilosc_podstawowa,
  3. (SUM(IF(ps.ps_skladnik NOT IN(15, 99),1,-1))) AS ilosc_dodatkowa
  4. FROM przepisy AS p, przepisy_skladniki AS ps
  5. WHERE p.id = ps.ps_przepis
  6. GROUP BY p.id
  7. HAVING ilosc_podstawowa=2 AND ilosc_dodatkowa>=5
  8. ORDER BY ilosc_dodatkowa


Głowię się nad tym od 2h i nie mogę tego ogarnąć :-//

Jak usunę w HAVING "AND ilosc_dodatkowa>=5" pokazuje elementy które spełniają warunek podstawowy (przepisy w których są tylko wymienione składniki),
zaś ilosc_dodatkowa w obu przypadkach wynosi -2
Gdy usunę cały zwrot HAVING otrzymuję wszystkie przepisy, ułożone od spełniających do niespełniających.

Tabela przepisy_skladniki ma następujące wpisy:
  1. ps_przepis(1) = ps_skladniki(1,2,5,6)
  2. ps_przepis(2) = ps_skladniki(99,15)
  3. ps_przepis(3) = ps_skladniki(162,164,234)
  4. ps_przepis(5) = ps_skladniki(15,99)
  5. ps_przepis(6) = ps_skladniki(8,51,53,15)
  6. ps_przepis(7) = ps_skladniki(1,29)
  7. ps_przepis(8) = ps_skladniki(25,331,99,340,234,15)


Wynik po całkowitym usunięciu klauzury HAVING jest następujący:
  1. nazwa | id | id_podstawowa | id_dodatkowa
  2. przepis(5) | 5 | 2 | -2
  3. przepis(2) | 2 | 2 | -2
  4. przepis(6) | 6 | -2 | 2
  5. przepis(7) | 7 | -2 | 2
  6. przepis(8) | 8 | -2 | 2
  7. przepis(3) | 3 | -3 | 3
  8. przepis(1) | 1 | -4 | 4


Ten post edytował d0m1n1k_ 3.09.2015, 19:21:05
Go to the top of the page
+Quote Post
trueblue
post
Post #18





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


  1. (SUM(IF(ps.ps_skladnik IN(15, 99),1,0))) AS ilosc_podstawowa,
  2. (SUM(IF(ps.ps_skladnik NOT IN(15, 99),1,0))) AS ilosc_dodatkowa
Go to the top of the page
+Quote Post
d0m1n1k_
post
Post #19





Grupa: Zarejestrowani
Postów: 208
Pomógł: 3
Dołączył: 13.07.2009
Skąd: Tarnów

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


Trochę przekombinowałem, ale

po zmianie zapytania na następujące:

  1. SELECT DISTINCT p.nazwa, p.id,
  2. (SUM(IF(ps.ps_skladnik IN(15, 99),1,0))) AS ilosc_podstawowa,
  3. (SUM(IF(ps.ps_skladnik NOT IN(15, 99),1,0))) AS ilosc_dodatkowa
  4. FROM przepisy AS p, przepisy_skladniki AS ps
  5. WHERE p.id = ps.ps_przepis
  6. GROUP BY p.id
  7. HAVING ilosc_podstawowa<=2 AND ilosc_dodatkowa<=3
  8. ORDER BY ilosc_podstawowa DESC, ilosc_dodatkowa ASC


Uzyskałem wynik już bardzo satysfakcjonujący:

  1. nazwa | id | ilosc_podstawowa | ilosc_dodatkowa
  2. przepis(5) | 5 | 2 | 0
  3. przepis(2) | 2 | 2 | 0
  4. przepis(6) | 6 | 1 | 3
  5. przepis(7) | 7 | 0 | 2
  6. przepis(3) | 3 | 0 | 3


ilosc_dodatkowa<=3 zmniejszyłem, aby wyeliminowało mi jakikolwiek przepis ;-)
Zastanawiam się jeszcze nad zmianą klauzury:
  1. HAVING ilosc_podstawowa<=2 AND ilosc_dodatkowa<=3

na
  1. HAVING ilosc_dodatkowa<=3

bo obecny efekt jest identyczny ale nie wiem czy jest to dobre rozwiązanie.
Go to the top of the page
+Quote Post
trueblue
post
Post #20





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

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


Wynik jest identyczny, ale to akurat przypadek.
Nie zawsze tak musi być.
Jeśli będziesz mieć przepis z czterema wybranymi składnikami i trzema innymi dodatkowymi, to przepis będzie spełniał tylko jeden z tych warunków (ten krótszy).
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 22.08.2025 - 21:25