Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Filtrowanie produktów po parametrach kategorii
Forum PHP.pl > Forum > Bazy danych > MySQL
sniver
Ponownie wracam z problemem. Tym razem nieco innym niż dotychczas..
Mianowicie chodzi mi o to że mam bazę produktów. Produkty oczywiście są skategoryzowane (wg. parent_id i drzewek ip - pomysł wzięty stąd). Do kategorii są przypisane parametry które mogą być wykorzystane przy dodawaniu produktu - podobnie jak na allegro...

Przy przeglądaniu listy produktów z jakiejś kategorii jest widoczny boks w którym można określić interesujące kogoś parametry - np. rodzaj paliwa (diesel, benzyna, lpg itp.).

No i teraz problem. Gdy ktoś wybierze tylko jeden parametr to sprawa jest załatwiona, ale jeśli ktoś wybierze 2 lub więcej, czyli np. rodzaj paliwa: lpg, lakier: metalic, kolor: zielony

Wtedy jest oczywiste że nie powinien brać każdego rekordu w którym któryś z tych parametrów występił, a jedynie te do których wszystkie parametry razem wzięte pasują.

czyli przykładowo baza zawiera:
1. Mercedes E320 - kolor: czarny, lakier: metalic, rodzaj paliwa: benzyna
2. Ford Mondeo - kolor: zielony, lakier: metalic, rodzaj paliwa: lpg
3. Opel Vectra - kolor: zielony, lakier: metalic, rodzaj paliwa: lpg

Wynik powinien pokazać 2 i 3 rekord, a nie wszystkie...

Próbowałem połączyć to zapytaniem z IN w warunku ale pokazuje wszystkie 3, z kolei jeśli chciałem wydzielić tylko i wyłącznie 2 rekordy odwołując się i dodając tabele z różnymi aliasami zapytanie zamula przy większej ilości danych...

Zapytanie co działa dobrze, ale wolno i jest nieeleganckie:
  1. SELECT
  2. `p`.`PRD_Name` AS `name`
  3.  
  4. FROM
  5. `products` AS `p`
  6. LEFT JOIN `productsparametr` AS `pp` ON (`pp`.`PRD_Id` = `p`.`PRD_Id`)
  7. LEFT JOIN `productsparametr` AS `pp2` ON (`pp2`.`PRD_Id` = `p`.`PRD_Id`)
  8. LEFT JOIN `productsparametr` AS `pp3` ON (`pp3`.`PRD_Id` = `p`.`PRD_Id`)
  9.  
  10. WHERE
  11. (`pp`.`PRV_Id` = 15) #Kolor: zielony
  12. AND (`pp2`.`PRV_Id` = 29) #Rodzaj paliwa: LPG
  13. AND (`pp3`.`PRV_Id` = 2) #Lakier: metalic



A oto zapytanie co działa szybko ale pokazuje za wiele:
  1. SELECT
  2. `p`.`PRD_Name` AS `name`
  3.  
  4. FROM
  5. `products` AS `p`
  6. LEFT JOIN `productsparametr` AS `pp` ON (`pp`.`PRD_Id` = `p`.`PRD_Id`)
  7.  
  8. WHERE
  9. (`pp`.`PRV_Id` IN (15, 29, 2))



Kilka słów o bazie:

products - tabela z produktami
PRD_Name - to nazwa produktu
PRD_Id - to id produktu

productsparametr - tabela z parametrami o produktach
PRV_Id - Id atrybutu (może sie potarzać w bazie)
PRD_Id - Id produktu do którego odwołuje sie ten parametr


Czy wie ktoś jak rozwiązać ten problem łatwo i bez nadmiernego chaosu?

Chyba się nie da tego inaczej zrobić niż na połączonych tabelach - będe obserwować ten temat - może ktoś wpadnie na ciekawy pomysł smile.gif
reaktor
Drugie zapytanie jest zupelnie nieprzydatne, bo IN
wybiera rekordy pasujace do ktorejkolwiek wartosci
z podanej mu listy.

Natomiast co do pierwszego: po co tak komplikowac?
  1. SELECT `p`.`PRD_Name` AS `name`
  2. FROM `products` AS `p`
  3. JOIN `productsparametr` AS `pp` ON (`pp`.`PRD_Id` = `p`.`PRD_Id`)
  4. WHERE 1=1
  5. AND (`pp`.`PRV_Id` = 15)
  6. AND (`pp`.`PRV_Id` = 29)
  7. AND (`pp`.`PRV_Id` = 2)

1=1 napisalem po to, zeby poszczegolne ANDy mozna bylo
doczepiac do zapytania na podstawie wyboru parametrow
przez uzytkownika.
sniver
znam tę metodę 1=1, ale to nie zadziała ;/
zresztą próbowałem. Szukałem po zagranicznych stronach i nigdzie indziej nie napotkałem się z innym rozwiązaniem niż łączenie tabel...

wymyśliłem inne zapytanie,

  1. SELECT DISTINCT
  2. `p`.`PRD_Id` AS `id`,
  3. `p`.`PRD_Name` AS `name`
  4. FROM
  5. `products` AS `p`
  6. JOIN `productsparametr` AS `pp` ON (
  7. (`pp`.`PRD_Id` = `p`.`PRD_Id`)
  8. AND (`pp`.`PRV_Id` IN (15,29,2))
  9. AND (
  10. (SELECT
  11. COUNT(1)
  12. FROM `productsparametr` AS `cpp`
  13. WHERE
  14. (`cpp`.`PRD_Id` = `p`.`PRD_Id`)
  15. AND ((`cpp`.`PRV_Id` = 15) OR (`cpp`.`PRV_Id` = 29) OR (`cpp`.`PRV_Id` = 2))
  16. ) = 3
  17. )
  18. )


te coś tam pod zapytanie równe 3 oznacza że wybrane 3 parametry są zliczone i przedstawione. Chciałbym by ktoś ocenił czy to zabije serwer czy może nie..
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.