Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL] Wybieranie rekordów
Forum PHP.pl > Forum > Bazy danych > MySQL
parzol
Witam.

Mam tabele:

id | atrakcja
==========
1 | aaaa
2 | bbbb

id | dom
======
1 | Basia
2 | Gosia
3 | Zosia

dom_id | atrakcja_id
==============
1 | 1
1 | 2
2 | 2
3 | 1

I jak wyświetlić nazwy domów dla których atrakcja_id przyjmuje wartość zarówno 1 jak i 2 (czyli w naszym przypadku zwroci tylko dom Basia) ?
nevt
zakładając, że twoje tabelki to: `domy`, `atrakcje` i `domy_atrakcje`:
  1. SELECT `dom` FROM `domy_atrakcje`LEFT JOIN `domy` ON `id` = `dom_id` GROUP BY `dom_id` HAVING COUNT(`atrakcja_id`) > 1;
pest
Nie dokładnie - zabrakło wyboru konkretnych atrakcji - przy większej liczbie atrakcji, wybierałoby jakikolwiek dom, który ma 2 lub więcej różnych atrakcji.

zakładając tabele:
`domy` (pola: `dom_id`, `dom`),
`atrakcje` (pola: `atrakcja_id`, `atrakcja`),
`domy_atrakcje` (pola: `dom_id`, `atrakcja_id`)

  1. SELECT `d`.`dom_id`, `dom`
  2. FROM `domy` da
  3. LEFT JOIN `domy_atrakcje` d ON `d`.`dom_id` = `da`.`dom_id`
  4. WHERE `atrakcja_id` IN (1,2)
  5. GROUP BY `d`.`dom_id`
  6. HAVING COUNT(`atrakcja_id`)=2;
parzol
Chyba się źle zrozumieliśmy nevt. Twój kod wyrzuca mi wszystkie nazwy domów w bazie. A nie o to chodziło.

pest - dzięki. Działa.
nevt
Cytat
Twój kod wyrzuca mi wszystkie nazwy domów w bazie. A nie o to chodziło.

NIEMOŻLIWE - sprawdzałem. Pokaż, dane źródłowe, pokaż wyniki i pokaż jakiem naprawdę kodem się posłużyłeś ?
parzol
Pest ci odpisał dlaczego to jest źle.

Jeszcze jedno pytanie. Bo kiedy dałem samo zapytanie wszystko działało pięknie. Ale teraz muszę to podczepić pod istniejące większe zapytanie. Wygląda to tak:

  1. SELECT r.id AS room_id, r.name AS room_name, p.id AS property_id, p.name AS property_name, c.name AS city, region.name AS region, p.standard, rg.file, MIN(rp.price) AS min_price, MAX(rp.price) AS max_price, GROUP_CONCAT(DISTINCT CONCAT(a.name, '*', a.icon) ORDER BY a.name SEPARATOR '|') AS attractions, r.description AS opis, r.bedroom_number AS l_sypialni, r.room_number AS l_pokoi, GROUP_CONCAT(DISTINCT CONCAT(t.name) ORDER BY t.name SEPARATOR '|') AS typ FROM room r LEFT JOIN property p ON r.property_id=p.id LEFT JOIN room_gallery rg ON rg.room_id=r.id LEFT JOIN room_price rp ON rp.room_id=r.id LEFT JOIN region ON p.region_id=region.id LEFT JOIN city c ON p.city_id=c.id LEFT JOIN property_attraction pa ON p.id=pa.property_id LEFT JOIN attraction a ON pa.attraction_id=a.id AND (a.is_active=1 OR a.is_active IS NULL) LEFT JOIN property_category pc ON p.id=pc.property_id LEFT JOIN room_type rt ON rt.room_id=r.id LEFT OUTER JOIN type t ON rt.type_id=t.id AND (t.is_active=1 OR t.is_active IS NULL) WHERE pa.attraction_id IN(1,9) GROUP BY pa.property_id HAVING COUNT(attraction_id)=2 GROUP BY room_id ORDER BY p.is_promoted DESC;



I oczywiście wywala błąd bo są dwa GROUP BY. Jak to zapisać żeby działało?
Kod bez klauzuli WHERE działa i wyrzuca wszystkie obiekty. A ja chce tylko te obiekty gdzie atrakcja ma np. ID = 1 i 9.

PS. GROUP BY pa.property_id, room_id nie działa.
nevt
Cytat
Pest ci odpisał dlaczego to jest źle.

Nieprawda - Pest wcale nie zakwestionował mojego rozwiązania tylko zaproponował bardziej szczegółowe rozwiązanie. To ty napisałeś że zwraca ci wszystkie rekordy z bazy co jest KŁAMSTWEM gdyż sprawdzałem to zapytanie na strukturze i danych które zamieściłeś w wątku.

Co do kolejnego problemu - cóż - poczekajmy na wypowiedź Pesta - po co mam się niepotrzebnie denerwować - powodzenia smile.gif
parzol
Spokojnie bez nerwów party.gif

Kod
mysql> SELECT p.name FROM property_attraction pa LEFT JOIN property p ON p.id=pa.property_id GROUP BY pa.property_id HAVING COUNT(pa.attraction_id) >1;
+---------------------+
| name                |
+---------------------+
| bella               |
| Supeeroo Vialnowa   |
| Relais santa chiara |
| La Collegiata       |
| Palazzo Mannaioni   |
| Il Borgo La Bagnaia |
+---------------------+
6 rows in set (0.00 sec)


Poza tym u ciebie w kodzie nie było chociażby klauzuli mówiącej o wybraniu konkretnych atrakcja_id więc już założenia są niespełnione.
Tak czy siak kod pest niezależnie działa tak jak chciałem.

Teraz potrzebuje pomocy jak to podpiąć pod to długie zapytanie. Ktoś pomoże? guitar.gif Z góry dzięki.
pest
Sorki za zamieszanie, nie o to mi chodziło. Oczywiście SQL podany przez nevt był dobry, do tamtych danych, ja go uszczegółowiłem - korzystając z tego co on napisał.

Co do długiego zapytania:
Tak jak już pisałem w PM zapytanie jest dość masakryczne, ale skoro wszystko jest potrzebne i taka jest konstrukcja tabel...
Lepiej dać kilka enterów do SQL'a, żeby było szybciej i prościej.

Nie będę analizował może całej struktury tabel, więc tylko ta zmiana w GROUP BY, jeśli nie będzie działało, to napisz jeszcze (bardzo możliwe, że może być coś jeszcze, nawet jak będzie dawało wyniki, to nie daję głowy, że o takie wyniki ci chodzi).

Pozatym, że nie wiem czy w ogóle mogą być 2x GROUP BY do jednego SELECT'a, to jeszcze był jeden problem taki, że `room_id` masz w kilku tabelach i nie podałeś, z której z nich to room_id było.

  1. SELECT r.id AS room_id,
  2. r.name AS room_name,
  3. p.id AS property_id,
  4. p.name AS property_name,
  5. c.name AS city,
  6. region.name AS region,
  7. p.standard,
  8. rg.file,
  9. MIN(rp.price) AS min_price,
  10. MAX(rp.price) AS max_price,
  11. GROUP_CONCAT(
  12. DISTINCT CONCAT(a.name, '*', a.icon)
  13. ORDER BY a.name SEPARATOR '|'
  14. ) AS attractions,
  15. r.description AS opis,
  16. r.bedroom_number AS l_sypialni,
  17. r.room_number AS l_pokoi,
  18. GROUP_CONCAT(
  19. DISTINCT CONCAT(t.name)
  20. ORDER BY t.name SEPARATOR '|'
  21. ) AS typ
  22. FROM room r
  23. LEFT JOIN property p ON r.property_id=p.id
  24. LEFT JOIN room_gallery rg ON rg.room_id=r.id
  25. LEFT JOIN room_price rp ON rp.room_id=r.id
  26. LEFT JOIN region ON p.region_id=region.id
  27. LEFT JOIN city c ON p.city_id=c.id
  28. LEFT JOIN property_attraction pa ON p.id=pa.property_id
  29. LEFT JOIN attraction a ON pa.attraction_id=a.id AND (a.is_active=1 OR a.is_active IS NULL)
  30. LEFT JOIN property_category pc ON p.id=pc.property_id
  31. LEFT JOIN room_type rt ON rt.room_id=r.id
  32. LEFT OUTER JOIN type t ON rt.type_id=t.id AND (t.is_active=1 OR t.is_active IS NULL)
  33. WHERE pa.attraction_id IN(1,9)
  34. GROUP BY r.id, pa.property_id
  35. HAVING COUNT(attraction_id)=2
  36. ORDER BY p.is_promoted DESC;
parzol
Dzięki za zainteresowanie. room_id to r.id oczywiście.
Ten kod nic nie wyrzuca. Nie ma błędów tylko po prostu "Empty set", a powinno poprawnie wyrzucić jeden obiekt.

sadsmiley02.gif
phpion
Już o tym rozmawialiśmy ale przedstawię mój pomysł na forum. Może komuś się przyda, a może i usłyszę jakieś opinie (za i przeciw).
Cytat(parzol @ 4.03.2008, 03:08:11 ) *
Witam.

Mam tabele:

id | atrakcja
==========
1 | aaaa
2 | bbbb

id | dom
======
1 | Basia
2 | Gosia
3 | Zosia

dom_id | atrakcja_id
==============
1 | 1
1 | 2
2 | 2
3 | 1

Ja bym zburzył nieco zasady tworzenia baz danych (postacie normalne) i do tabeli z domami dodał kolumnę "attractions", która wyglądałaby dla tego przykładu w ten sposób:
Kod
id | dom   | attractions
=======================
1  | Basia | 1,2
2  | Gosia | 2
3  | Zosia | 1

czyli zawierałaby id atrakcji z tabeli "dom_atrakcja" dla danego domu. Ważne aby id były posortowane (czyli 1,2, a nie 2,1). Później w wyszukiwarce przesyłamy zaznaczone atrakcje w tablicy i łączymy np. implode(',', $_POST['attractions']) do ciągu x,y,z,* po czym możemy sprawdzić, który dom pasuje do zaznaczonych atrakcji poprzez zwykłe LIKE attrations="%$polaczone%". Rozwiązanie wydaje mi się prostsze i wydajniejsze.

Kwestia po co tworzyć więc tabelę "dom_atrakcja". Ano po to aby przy wyświetlaniu danego obiektu łatwo (1 proste zapytanie z joinem) wyświetlić jego atrakcje. Czyli z dodatkowej kolumny korzystamy tylko przy wyszukiwaniu, a przy wyświetlaniu szczegółów obiektu korzystamy już z tej "standardowej".

Aktualizację pola można robić w PHP ale w sumie chyba lepiej/wygodniej napisać do tego triggera.

To mój pomysł guitar.gif
parzol
Wspaniały pomysł phpionie yahoo.gif

Nowatorsko, odważnie ale nie działa w każdym przypadku !

Nie przewidziałeś drobnej sytuacji kiedy ciąg atrakcji ma postać 1_2_3_9 a ktoś wyszuka według 1_9.
Ale to szczegóły. Wystarczy te '_' usunąć (są zbędne a wręcz niepożądane!) i wyszukiwać tak: LIKE("%1%9%").

Jednak za samą idee gratki i wielkie dzięki! wub.gif
phpion
Cytat(parzol @ 7.03.2008, 13:54:16 ) *
Nie przewidziałeś drobnej sytuacji kiedy ciąg atrakcji ma postać 1_2_3_9 a ktoś wyszuka według 1_9.

Faktycznie, masz rację - o tym nie pomyślałem :/

Cytat(parzol @ 7.03.2008, 13:54:16 ) *
Wystarczy te '_' usunąć (są zbędne a wręcz niepożądane!) i wyszukiwać tak: LIKE("%1%9%").

No nie do końca. Taki zapis wyszuka Ci zarówna ciąg 1_9 (czyli to o co Ci chodziło) oraz np. 1_19 (co już będzie błędem). Heh, chyba mój pomysł nie jest taki genialny wstydnis.gif
parzol
Cytat(phpion @ 7.03.2008, 13:40:55 ) *
No nie do końca. Taki zapis wyszuka Ci zarówna ciąg 1_9 (czyli to o co Ci chodziło) oraz np. 1_19 (co już będzie błędem).


Hmmm fakt. A jakby zapisywać w bazie dane tak: _1_2_9_ i szukać według: LIKE("%_1_2_%_9_%"). ? Rkingsmiley.png

Cytat(phpion @ 7.03.2008, 13:40:55 ) *
Heh, chyba mój pomysł nie jest taki genialny wstydnis.gif


Nie bądź dla siebie taki surowy smile.gif Jako jedyny dałeś działające rozwiązane na 4 forach!
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.