Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Problem z zapytaniem. Niby proste a jednak
Forum PHP.pl > Forum > Bazy danych > MySQL
Rafix24
Witam,
Problem jest blahy na pierwszy rzut oka ale napsul mi wystarczajaco duzo krwi a i tak nie wiem jak go rozwiazac wiec zwracam sie do Was o pomoc.

Mam 3 tabele Restauracje, Posilki_Restauracji, Posilki.

:arrow: Restauracje (id_rest,.....)
:arrow: Posilki (id_pos, nazwa_pos)
:arrow: Posilki_Restauracji (id_rest, id_pos)

Restauracje moga miec zero lub wiele posilkow.

Uzytkownik chce znalezc restauracje, ktora oferuje jednoczesnie np. pizze (id_pos=1), hamburgery (id_pos=2) i hot-dogi (id_pos=3).

PYTANIE : Jakie zadac zapytanie do bazy, by zwrocila id_rest tylko takich restauracji, ktore spelniaja wszystkie 3 warunki (warunkow moze byc oczywiscie dowolna ilosc ograniczona jedynie iloscia zdefinowanych posilkow w tabeli Posilki) ?!?

Po trzech bezowocnych godzinach siedzenia nad tym zupelnie stracilem koncepcje i wiare ze mozna to zrobic...

Bardzo licze na pomoc
spenalzo
[sql:1:20a732fbe0]SELECT r.* FROM restauracje r, posilki_restauracji pr, posilki p WHERE r.id_rest=pr.id_rest AND pr.id_pos=p.id_pos AND p.id_pos IN (1,2,3) GROUP BY r.id_rest[/sql:1:20a732fbe0]
lub
[sql:1:20a732fbe0]SELECT r.* FROM restauracje r LEFT JOIN posilki_restauracji pr ON (r.id_rest=pr.id_rest) LEFT JOIN posilki p ON (pr.id_pos=p.id_pos) WHERE p.id_pos IN (1,2,3) GROUP BY r.id_rest[/sql:1:20a732fbe0]
:?:
Rafix24
Witam,
Dzieki spenalzo za odp ale to zapytanie (te zapytania) niestety nie dziala prawidlowo sad.gif
Przede wszystkim wyszukuje tylko dla pierwszego warunku zdefiniowanego w IN(1,2,3) czyli tylko dla 1. Poza tym wyswietla wszystkie restauracje, ktore maja ten posilek w ofercie (a nie tylko te ktore maja wszystkie 3 w ofercie), co jest oczywiste z uwagi na fakt, ze wyszukuje tylko po pierwszym warunku w IN(1,2,3,...)

Moze jednak ktos wpadnie na pomysl jak rozwiazac ten problem, bo juz mi rece opadaja :cry:
spenalzo
[sql:1:bc7a64c8df]SELECT r.* FROM restauracje r LEFT JOIN posilki_restauracji pr ON (r.id_rest=pr.id_rest) LEFT JOIN posilki p ON (pr.id_pos=p.id_pos) WHERE p.id_pos=1 AND p.id_pos=2 AND p.id_pos=3 GROUP BY r.id_rest[/sql:1:bc7a64c8df]
Rafix24
Niestety nic nie zwraca. Chyba jest problem z tym, ze szuka takiej restauracji gdzie w Posilki_Restauracji sa naraz (w jednym rekordzie) id_pos=1, id_pos=2, ... - a taki warunek nie zostanie nigdy spelniony bo w jednym rekordzie jest tylko jeden id_pos.
spenalzo
No to zmień AND na OR.

A jak masz to podaj zrzut bazy i pare przykładowych insertów zebym mógł sprawdzić a nie wróżyć dalej. winksmiley.jpg
Rafix24
Jak zmienie AND na OR to znowu wyswietla restauracje, ktore maja w ofercie ktorykowiek z zadanych posilkow.

[sql:1:cea7dca7ba]
CREATE TABLE Restauracje(
id_rest int auto_increment primary key,
nazwa_rest char(10)
);
CREATE TABLE Posilki(
id_pos int auto_increment primary key,
nazwa_pos char(10)
);
CREATE TABLE Posilki_Restauracji(
id_rest int,
id_pos int
);

INSERT INTO Restauracje (nazwa_rest) VALUES ('Pierwsza');
INSERT INTO Restauracje (nazwa_rest) VALUES ('Druga');
INSERT INTO Restauracje (nazwa_rest) VALUES ('Trzecia');
INSERT INTO Restauracje (nazwa_rest) VALUES ('Czwarta');
INSERT INTO Restauracje (nazwa_rest) VALUES ('Piata');

INSERT INTO Posilki (nazwa_pos) VALUES ('Pizza');
INSERT INTO Posilki (nazwa_pos) VALUES ('Hamburger');
INSERT INTO Posilki (nazwa_pos) VALUES ('Hot-dog');
INSERT INTO Posilki (nazwa_pos) VALUES ('Kebab');
INSERT INTO Posilki (nazwa_pos) VALUES ('Gyros');

INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('1','1');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('1','2');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('1','3');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('1','4');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('1','5');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('2','2');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('2','3');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('2','4');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('2','5');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('3','3');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('3','4');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('3','5');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('4','4');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('4','5');
INSERT INTO Posilki_Restauracji (id_rest,id_pos) VALUES ('5','5');

[/sql:1:cea7dca7ba]

Mysle ze to zupelnie wystarczy smile.gif
Niecierpliwie czekam na rezultaty biggrin.gif
spenalzo
Hmm przyjrze sie temu jutro (bo jest już troche późno) ale jedyny sposób to taki:
[sql:1:6ea5c7cbf5]SELECT r.*
FROM restauracje r, posilki_restauracji pr,posilki_restauracji pr2, posilki_restauracji pr3 WHERE r.id_rest=pr.id_rest AND pr.id_pos = 1 AND pr2.id_pos = 2 AND pr3.id_pos = 3 GROUP BY r.id_rest[/sql:1:6ea5c7cbf5]
Czyli tyle dołączeń tabeli ile szukanych posiłków.

Przy okazji - pozakładaj indeksy w tabeli posilki_restauracje, przyspieszy szukanie.
Rafix24
Niestety znowu to samo :cry:
Zwraca restauracje, ktore maja ktorykolwiek z zadanych posilkow w ofercie a nie tylko te, ktore maja wszystkie z zadanych posilkow ...

Moze jeszcze komus zechce sie wkleic kod sqla i pokombinowac - bede na prawde wdzieczny 8)
shima
Jeżeli ma to być czyste zapytanie mysql, to nie podejmuje się, bo chyba się nie da (może się mylę), ale jeżeli może to być skrypt php, to jutro napiszę. Na dziś dosyć 8)

?>[/php]
spenalzo
Cytat
Zwraca restauracje, ktore maja ktorykolwiek z zadanych posilkow w ofercie a nie tylko te, ktore maja wszystkie z zadanych posilkow ...

Niemożliwe, u mnie działa (pokazuje restauracje 1).

Innego sposobu nie znam.
Rafix24
Shima, oczywiscie ze nie ma to byc czyste zapytanie sql. Skrypt php jak najbardziej mile widziany smile.gif

Spenalzo, zapytanie w postaci :
[sql:1:5bfe631829]SELECT r.*
FROM restauracje r, posilki_restauracji pr,posilki_restauracji pr2, posilki_restauracji pr3
WHERE r.id_rest=pr.id_rest AND pr.id_pos = 1 AND pr2.id_pos = 2 AND pr3.id_pos = 3
GROUP BY r.id_rest
[/sql:1:5bfe631829]

zwraca, tak jak mowilem, restauracje, ktore maja jeden z zadanych posilkow a nie tylko te, ktore maja je wszystkie jednoczesnie.

Jednak jak zmieni sie troche Twoje zapytanie na :

[sql:1:5bfe631829]SELECT r.*
FROM restauracje r, posilki_restauracji pr,posilki_restauracji pr2, posilki_restauracji pr3
WHERE r.id_rest=pr.id_rest AND r.id_rest=pr2.id_rest AND r.id_rest=pr3.id_rest AND pr.id_pos = 1 AND pr2.id_pos = 2 AND pr3.id_pos = 3
GROUP BY r.id_rest
[/sql:1:5bfe631829]
wydaje sie ze to dziala prawidlowo - potestowalem troche i zwraca dobre wyniki.
Moze zle przepisales wczesniejsze zapytanie i dlatego u Ciebie to chodzilo a u mnie nie smile.gif

Zrobie wiecej INSERTow i potestuje na wiekszej bazie, ale wydaje sie ze to jednak TO...
Wielkie dzieki Spenalzo biggrin.gif

Inne rozwiazania bardzo mile widziane.
spenalzo
Tak jak mówiłem (pisałem tongue.gif) to jest wg mnie jedyne rozwiązanie... :?
Na pewno nie jest ono wydajne, bo przy 3 szukanych posiłkach dołącza sie trzy tabele - ale jak bedziesz szukał np. 15 posiłków to musisz dołączyć 15 razy tą samą tabelę i napisać warunki :? sad.gif

Przy okazji - dodaj sobie klucze na obydwie kolumny w tabeli posilki_restauracje - zwiekszy wydajność.
Piasiu
A może tak:
[sql:1:64e42f071a]SELECT r.*
FROM restauracje r, posilki_restauracji pr WHERE r.id_rest=pr.id_rest AND (pr.id_pos = 1 OR pr.id_pos = 2 OR pr.id_pos = 3)
GROUP BY r.id_rest[/sql:1:64e42f071a]
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.