Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL] Problem z joinami
Forum PHP.pl > Forum > Bazy danych > MySQL
Vielta
Hej,
mam do napisania dość spore zapytanie do bazy, które ma za zadanie pobierać listę restauracji (pobiera listę, z innej tabeli średnią ocen - to niby działa). Ostatnio przyszła potrzeba dodania sortowania i pobierania po tagach/filtrowania. Tu jest problem bo nie chce działać, czy mógłby ktoś poradzić jak to naprawić? Działa jeśli zamiast AND przy tagach dam OR ale przecież nie o to chodzi - chcę tylko restauracje które zawierają wszystkie podane tagi. Poniżej wklejam zapytanie SQL/kod w ZF/schemat bazy. Przy okazji, count(t.id) zwraca ilość wszystkich tagów przypisanych do wszystkich rekordów, też nie wiem czemu.
  1. SELECT `r`.`id`, `r`.`name`, `r`.`address`, `r`.`description`, `r`.`city`, IF(add_date >= (now() - interval 2 week), ' nowość', '') AS `isnew`, avg(p.rank) AS `points`, `rt`.`id` AS `rtid`, count(t.id) AS `tag_count` FROM `restaurants` AS `r` LEFT JOIN `rate` AS `p` ON p.rid = r.id INNER JOIN `tagged_restaurants` AS `rt` ON rt.restaurant_id = r.id INNER JOIN `tags` AS `t` ON t.id = rt.tag_id WHERE (t.tag = 'polska') AND (t.tag = 'karta') GROUP BY `r`.`id` ORDER BY `tag_count` DESC LIMIT 8


  1. public function getAll($filter = null, $sort = null) {
  2. $select = $this->select()
  3. ->from(array('r' => 'restaurants'), array('r.id', 'r.name', 'r.address', 'r.description', 'r.city', 'isnew' => new Zend_Db_Expr(" if(add_date >= (now() - interval 2 week), ' nowość', '')")))
  4. ->setIntegrityCheck(false)
  5. ->joinLeft(array('p' => 'rate'), 'p.rid = r.id', array('points' => new Zend_Db_Expr('avg(p.rank)')));
  6. if($filter != null) {
  7. $filter = explode(',', $filter);
  8. $select->join(array('rt' => 'tagged_restaurants'), 'rt.restaurant_id = r.id', array('rtid' => 'rt.id'));
  9. $select->join(array('t' => 'tags'), 't.id = rt.tag_id', array('tag_count' => 'count(t.id)'));
  10.  
  11. foreach($filter as $f) {
  12. $select->where($this->getDefaultAdapter()->quoteInto('t.tag = ?', $f)); // Jak tu wstawię orWhere to zaczyna działać, ale nie tak jak oczekuję
  13. }
  14.  
  15. if($sort == 'r.id') {
  16. $select->order('tag_count desc');
  17. }
  18. }
  19. if($filter == null) {
  20.  
  21. $select->order($sort);
  22. }
  23. $select->group('r.id');
  24.  
  25. return $select;
  26. }


Tabele:
tags: id, tag
tagged_restaurants: id, restaurant_id, tag_id
restaurants: id, name, address (w sumie tylko te są ważne)
rate: id, rid (id restauracji), rank (ocena)


Proszę o pomoc smile.gif
maly_swd
  1. SELECT `r`.`id`, `r`.`name`, `r`.`address`, `r`.`description`, `r`.`city`, IF(add_date >= (now() - interval 2 week), ' nowość', '') AS `isnew`, avg(p.rank) AS `points`, `rt`.`id` AS `rtid`, count(t.id) AS `tag_count` FROM `restaurants` AS `r` LEFT JOIN `rate` AS `p` ON p.rid = r.id INNER JOIN `tagged_restaurants` AS `rt` ON rt.restaurant_id = r.id INNER JOIN `tags` AS `t` ON t.id = rt.tag_id WHERE (t.tag = 'polska') OR (t.tag = 'karta') GROUP BY `r`.`id` HAVING count(DISTINCT t.id)=2 ORDER BY `tag_count` DESC LIMIT 8


Having count( distinct t.id) =2 to da Ci tylko wynik tam gdzie sa dwa unikalne tagi, jak w WHERE dasz trzy tagi to tu tez musisz dac trzy
*distinct po to by nie wiem czy dane przy joinach CI sie nie dubluja. Co wskazuje twoja zmienna tag_count?? czy ma wartosc 2 czy inna?

musi byc OR w WHERE bo t.tag w jednej chwili nie moze miec 2 wartosci:)

* to jest zupelnie nieoptymalizowane zapytanie ale podalem Ci naprowadzenie
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.