Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Filtr produktów
starcode
post 22.03.2009, 21:02:22
Post #1





Grupa: Zarejestrowani
Postów: 28
Pomógł: 0
Dołączył: 18.06.2006

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


Witam!

Piszę obecnie skrypt bazy produktów (dajmy na to komputerów, gdzie mamy monitory, laptopy, drukarki itp. itd.).
Pojawia się problem / pytanie jak wykonać filtrowanie produktów (czyli pokazywanie produktów o określonych paramterach, np.: matryca, bateria, system operacyjny, procesor, producent itp.).

Tabela produktu zawiera podstawowe dane (id, nazwa, cena, opis, zdjęcie, grupa_id, kategoria_id, podkategoria_id).
Tabela parametrów zawiera: id, id_paramteru, id_produktu, wartosc_paramteru
Tabela nazw paramterów zawiera id, nazwa

Tabela nazw param. jest połączona z tabelą param. relacją jeden do wielu (jedna nazwa param. do wielu wartości param.)
Tabela param. z tabelą produktów połączona jest relacją wiele do jednego (jeden produkt może mieć wiele paramterów)

Pytanie: Jak teraz pobrać te produkty, które mają np. system operacyjny = Windows XP i producent = ASUS?

Jest to dla mnie teraz zagadka i nie wiem jak ugryźć temat.
Go to the top of the page
+Quote Post
Spawnm
post 22.03.2009, 21:12:44
Post #2





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




join i where w zapytaniu sql .
Go to the top of the page
+Quote Post
starcode
post 22.03.2009, 21:45:02
Post #3





Grupa: Zarejestrowani
Postów: 28
Pomógł: 0
Dołączył: 18.06.2006

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


Możesz podać przykładowe zapytanie?

Graficznie struktura tabeli wygląda tak:

tabela nazwy_parametrow

Kod
+-------+---------------------+
|  id   | nazwa_paramteru     |
+-------+---------------------+
|   1   | system operacyjny   |
+-------+---------------------+
|   2   | producent           |
+-------+---------------------+
|   3   | procesor            |
+-------+---------------------+
|   4   | przekatna matrycy   |
+-------+---------------------+


tabela parametry (łączy wartosci paramterów z nazwami paramterow i przypisuje do konkretnego produktu)

Kod
+----------------+----------------+------------------------------+
| id_paramteru   |  id_produktu   | wartosc_paramteru            |
+----------------+----------------+------------------------------+
| 1              |   20           | Windows XP                   |
+----------------+----------------+------------------------------+
| 1              |   21           | Windows XP                   |
+----------------+----------------+------------------------------+
| 1              |   22           | Windows Vista                |
+----------------+----------------+------------------------------+
| 1              |   23           | Windows XP                   |
+----------------+----------------+------------------------------+
| 1              |   24           | Brak systemu                 |
+----------------+----------------+------------------------------+
| 2              |   20           | Asus                         |
+----------------+----------------+------------------------------+
| 2              |   21           | Acer                         |
+----------------+----------------+------------------------------+
| 2              |   22           | Asus                         |
+----------------+----------------+------------------------------+
| 2              |   23           | Asus                         |
+----------------+----------------+------------------------------+
| 2              |   24           | Asus                         |
+----------------+----------------+------------------------------+


I chcę pobrać produkty, które mają:
(`id_paramteru`='1' AND `wartosc_paramteru`='Windows XP') AND (`id_paramteru`='2' AND `wartosc_paramteru`='Asus')

Powinno zwrócić rekordy (produkty) o `id_produktu: 20 i 23.

Oczywiście istnieje jeszcze tabela produkt, która ma ID i owo ID jest wpisane w tabeli `parametry` w polu `id_produktu`

Ten post edytował starcode 22.03.2009, 21:46:10
Go to the top of the page
+Quote Post
Spawnm
post 23.03.2009, 10:02:06
Post #4





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




no to to chyba by było tak:

  1. SELECT produkty.nazwa FROM produkty, parametry WHERE produkty.id=parametry.id_produktu AND parametry.id_paramteru='1' AND parametry.wartosc_paramteru='Windows XP' AND parametry.id_paramteru='2' AND parametry.wartosc_paramteru='Asus' "


zobacz czy działa smile.gif
Go to the top of the page
+Quote Post
starcode
post 23.03.2009, 10:23:36
Post #5





Grupa: Zarejestrowani
Postów: 28
Pomógł: 0
Dołączył: 18.06.2006

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


Cytat(Spawnm @ 23.03.2009, 10:02:06 ) *
no to to chyba by było tak:

  1. SELECT produkty.nazwa FROM produkty, parametry WHERE produkty.id=parametry.id_produktu AND parametry.id_paramteru='1' AND parametry.wartosc_paramteru='Windows XP' AND parametry.id_paramteru='2' AND parametry.wartosc_paramteru='Asus' "


zobacz czy działa smile.gif


Nie ma szans na działanie.

W tym wypadku próbujesz pobrać rekord który zarazem id_paramteru ma równe 2 i jeden, a wartosc_paramteru jest zarazem równa Asus jak i Windows XP. OR tutaj nic nie zmiania, ponieważ zwrócone zostaną zarówno produkty z Windows XP i Acerem jak i z Windowsem Vista i Asusem.
Go to the top of the page
+Quote Post
Noddi
post 23.03.2009, 10:33:37
Post #6





Grupa: Zarejestrowani
Postów: 45
Pomógł: 7
Dołączył: 25.12.2004
Skąd: Kraków

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


  1. SELECT produkty.nazwa FROM (SELECT result1.id_produktu FROM (SELECT parametry.id_produktu FROM parametry WHERE parametry.wartosc_parametru='Windows XP') AS result1 INNER JOIN (SELECT parametry .id_produktu FROM parametry WHERE parametry.wartosc_parametru='Asus') AS result2 ON result1.id_produktu=result2.id_produktu) AS result INNER JOIN produkty ON result.id_produktu=produkty.id;


Ale jest to rozwiązanie mało optymalne i wydajne.

Ten post edytował Noddi 23.03.2009, 10:39:40


--------------------
"Yes, experience matters. No, one year repeated fifteen times does not count."
bartoszlugowski.com
Go to the top of the page
+Quote Post
starcode
post 23.03.2009, 10:50:57
Post #7





Grupa: Zarejestrowani
Postów: 28
Pomógł: 0
Dołączył: 18.06.2006

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


No fakt, za bardzo optymalne nie jest.

Być może jest jakieś lepsze wyjście, aby utworzyć filtr produktów?
Go to the top of the page
+Quote Post
Spawnm
post 23.03.2009, 11:10:50
Post #8





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




a nie zastanawiałeś się może nad rozbiciem tabeli na dwie?
tabela z systemami i tabela z firmą kompa ?
wtedy sprawa była by prosta , dodatkowo była by jakaś segregacja a nie wszystko w 1 worku smile.gif
Go to the top of the page
+Quote Post
Noddi
post 23.03.2009, 11:13:12
Post #9





Grupa: Zarejestrowani
Postów: 45
Pomógł: 7
Dołączył: 25.12.2004
Skąd: Kraków

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


Można zrobić też tak, myślę, że lepsze rozwiązanie:

  1. SELECT produkty.nazwa FROM (SELECT SUM(CASE WHEN parametry.wartosc_parametru='Windows XP' THEN 1 ELSE 0 END) AS windows_xp, SUM(CASE WHEN parametry.wartosc_parametru='Asus' THEN 1 ELSE 0 END) AS asus, parametry.id_produktu FROM parametry GROUP BY parametry.id_produktu) AS result INNER JOIN produkty ON result.id_produktu=produkty.id WHERE result.windows_xp=1 AND result.asus=1;


--------------------
"Yes, experience matters. No, one year repeated fifteen times does not count."
bartoszlugowski.com
Go to the top of the page
+Quote Post
starcode
post 23.03.2009, 12:03:26
Post #10





Grupa: Zarejestrowani
Postów: 28
Pomógł: 0
Dołączył: 18.06.2006

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


Cytat(Spawnm @ 23.03.2009, 11:10:50 ) *
a nie zastanawiałeś się może nad rozbiciem tabeli na dwie?
tabela z systemami i tabela z firmą kompa ?
wtedy sprawa była by prosta , dodatkowo była by jakaś segregacja a nie wszystko w 1 worku smile.gif


No własnie nie moge tak zrobic. Poniewaz paramterow moze byc bardzo duzo (jak pisałem, to nie beda tylko laptopy, ale i inne sprzety), wiec nie zawsze np. system operacyjny bedzie wlasciwym parametrem).

Zreszta struktura bazy wowczas zbyt wplywa na ilosc danych przechowywanych w bazie (bo umozliwia mi zapisanie tylko tych paramterow, dla ktorych sa tabele).
Go to the top of the page
+Quote Post
Spawnm
post 23.03.2009, 12:24:24
Post #11





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




hmmm nie do końca chyba zrozumiałem ;P

przecież musisz z góry założyć czego będziesz szukać przez select.
tak więc można by wypisać jakie parametry mogły by występować i do tego dać 1 tabele
typu id_produktu, system, firma, inne
wtedy jest wszystko na swoim miejscu a nie w 1 worku , dodatkowo bardzo łatwo robić zapytania smile.gif
Go to the top of the page
+Quote Post
starcode
post 23.03.2009, 12:37:03
Post #12





Grupa: Zarejestrowani
Postów: 28
Pomógł: 0
Dołączył: 18.06.2006

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


Całość nie bedzie na tyle statyczna, aby tworzyc tabele pod konkretne wartosci.
To musi być bardzo skalowalne. Dodanie (uzupełnienie) danych w tych tabelach w ten sposob (przynajmniej w przypadku mojego projektu) moze / czy raczej jest bardzo problematyczne i nie wiem czy wogole sensownie wykonywalne.

Oczywiscie zakladajac ze dane juz mamy w bazie - owszem, taka struktura jest bardzo wygodna.
Go to the top of the page
+Quote Post
ddiceman
post 23.03.2009, 13:15:43
Post #13





Grupa: Zarejestrowani
Postów: 326
Pomógł: 121
Dołączył: 23.07.2008
Skąd: Wrocław

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


Sprobuj cos w stylu
  1. SELECT
  2. id_produktu,
  3. SUM(
  4. IF(id_parametru = 1 AND wartosc_parametru = 'Windows XP', 1, /* kazdy warunek */
  5. IF(id_parametru = 2 AND wartosc_parametru = 'Asus', 1,
  6. 0
  7. )) /* tyle nawiasow zamykajacych, ile warunkow */
  8. ) AS warunek
  9. FROM parametry LEFT JOIN nazwy_parametrow ON (parametry.id_parametru = nazwy_parametrow.id)
  10. WHERE id_parametru IN (1, 2) /* to do dziala niepotrzebne, ale w celach optymalizacji */
  11. GROUP BY id_produktu
  12. HAVING warunek = 2 /* taka liczba, ile warunkow*/ ;


Ten post edytował ddiceman 23.03.2009, 13:47:19
Go to the top of the page
+Quote Post
starcode
post 23.03.2009, 17:11:03
Post #14





Grupa: Zarejestrowani
Postów: 28
Pomógł: 0
Dołączył: 18.06.2006

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


W sumie zapytanie powyżej jest całkiem niezłe - trzeba przyznać.

Tylko niepotrzebnie było łączone z nazwami paramterów (być może ja niepotrzebnie wogóle o tym wspomniałem zagmatwując całą systuację).

Pytanie teraz w jaki sposób połączyć to zapytanie, aby połaczyć to zapytanie nie z nazwami parametrów a z produktami:

  1. SELECT
  2. parametry.id_produktu, produkty.nazwa,
  3. SUM(
  4. IF(id_parametru = 1 AND wartosc_parametru = 'Windows XP', 1,
  5. IF(id_parametru = 2 AND wartosc_parametru = 'Asus', 1,
  6. 0
  7. ))
  8. ) AS warunek, MIN(cena) AS cena_minimalna
  9. FROM parametry LEFT JOIN produkty ON (parametry.id_produktu = produkty.id_produktu)
  10. WHERE id_parametru IN (1, 2) AND produkty.STATUS='1'
  11. GROUP BY id_produktu
  12. HAVING warunek = 2


Ale niestety nie działa? Co źle?
Go to the top of the page
+Quote Post
ddiceman
post 23.03.2009, 17:38:51
Post #15





Grupa: Zarejestrowani
Postów: 326
Pomógł: 121
Dołączył: 23.07.2008
Skąd: Wrocław

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


  1. SELECT
  2. parametry.id_produktu, produkty.nazwa,
  3. SUM(
  4. IF(id_parametru = 1 AND wartosc_parametru = 'Windows XP', 1,
  5. IF(id_parametru = 2 AND wartosc_parametru = 'Asus', 1,
  6. 0
  7. ))
  8. ) AS warunek, MIN(cena) AS cena_minimalna, COUNT(produkty.id) AS warunek2
  9. FROM parametry LEFT JOIN produkty ON (parametry.id_produktu = produkty.id_produktu AND produkty.STATUS='1')
  10. WHERE id_parametru IN (1, 2)
  11. GROUP BY id_produktu
  12. HAVING warunek = 2 AND warunek2 = 2

Zeby nie laczyc nieaktywnych produktow, bo wtedy nie wyjdzie Ci to wyliczenie warunek i zeby zliczac tylko zlaczenia z aktywnymi warunek2

Ten post edytował ddiceman 23.03.2009, 17:40:28
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 3.07.2025 - 22:50