Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Zapytanie wyszukujące na podstawie parametrów (tak jak na allegro)
lorak110786
post
Post #1





Grupa: Nieautoryzowani
Postów: 34
Pomógł: 1
Dołączył: 22.06.2009
Skąd: Koszalin/Poznań

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


Witam. Mam następujący problem:
Są 2 tabele:
produkty, parametry

w tabeli 'produkty' są pola:
id_produktu, nazwa

w tabeli 'parametry' są pola:
id_produktu, parametr, wartosc

Omawiając. Każdy produkt ma kilka parametrów. Każdy parametr ma jakąś wartość. Mam 3 produkty: pr1, pr2, pr3. Mam też ogólnie 3 parametry: wys, szer, waga. Łącznie w tabeli 'parametry' mam 9 rekordów, po 3 pary >parametr i wartość parametru< dla każdego z produktów.

Chciałbym napisać takie zapytanie które wybierze mi produkty spełniające WSZYSTKIE określone warunki w jednym zapytaniu czyli np: 'wys' BETWEEN 30 AND 100, oraz 'szer' BETWEEN 60 AND 100 oraz 'waga' BETWEEN 10 AND 100

Próbowałem już kombinować na różne sposoby, ale nie chce mi wyjść. Otrzymuję albo wyniki produktów spełniających dowolne kryterium, lub jeśli w HAVING użyję "AND" - brak wyników, co jest oczywiste gdyż nie ma dwóch rekordów spełniających warunki na AND.

  1. SELECT *
  2. FROM products
  3. LEFT JOIN products_values vals USING(id_product)
  4. HAVING (vals.id_label=61 AND vals.value BETWEEN 100 AND 500) OR (vals.id_label=63 AND vals.value BETWEEN 15 AND 30)


Ma ktoś na to jakiś mądry sposób? Z góry dziękuję za podpowiedzi.

Ten post edytował lorak110786 5.10.2010, 14:40:09
Go to the top of the page
+Quote Post
TheTester
post
Post #2





Grupa: Zarejestrowani
Postów: 30
Pomógł: 0
Dołączył: 11.03.2009

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


Nie wiem jak to zadziała, bo pisane bez sprawdzania, ale ja bym to chyba tak zrobił:

  1. SELECT * FROM products p, products_values v WHERE p.id=v.id_product AND ((v.id_label=61 AND v.value BETWEEN 100 AND 50) OR (v.id_label=63 AND v.value BETWEEN 15 AND 30))
Go to the top of the page
+Quote Post
lorak110786
post
Post #3





Grupa: Nieautoryzowani
Postów: 34
Pomógł: 1
Dołączył: 22.06.2009
Skąd: Koszalin/Poznań

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


No to jest pierwsza rzecz jaką próbowałem zrobić. Niestety wybiera źle. Wybiera rekordy które spełniają dowolne z warunków (gdyż użyte jest OR).
Go to the top of the page
+Quote Post
TheTester
post
Post #4





Grupa: Zarejestrowani
Postów: 30
Pomógł: 0
Dołączył: 11.03.2009

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


Hmm...Opierałem się na tym przykładzie, co wstawiłeś. Gdybym chciał pobrać wszystkie produkty, które spełniają pewne założenia, to bym zrobił coś takiego:

  1. SELECT * FROM products p, products_values v WHERE p.id=v.id_product AND v.value1 BETWEEN 50 AND 100 AND v.value2 BETWEEN 15 AND 30

Coś takiego powinno zwrócić wszystkie produkty, których value1 zawiera się w przedziale 50-100 a value2 w przedziale 15-30.
Go to the top of the page
+Quote Post
nospor
post
Post #5





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Trzeba zastosować podobne rozwiązanie jak tu:
http://forum.php.pl/index.php?s=&showt...st&p=793421
Go to the top of the page
+Quote Post
sniver
post
Post #6





Grupa: Zarejestrowani
Postów: 159
Pomógł: 5
Dołączył: 31.08.2007

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


w serwisie erobay.pl zastosowałem taki oto format:

Kategorie produktów, a do każdej (zaczynając od rodzica - potomkowie dziedziczą parametry) dodałem parametry.

Każdy z nich zadeklarowałem w/g takich wartości jak: checkbox, select i range.

Każde z nich ma na celu dać użytkownikowi pożądany sposób przefiltrowania informacji oraz przy wysłaniu formularza przygotowanie odpowiedniego zapytania do bazy danych.

I tak w przypadku jeśli parametrem jest checkbox wtedy każdy kolejny parametr z tej grupy rozdzielany jest jako OR (tak by dopasować maksymalnie dużo pasujących wyników).
Gdy wybierze ktoś select to wtedy tylko i wyłącznie wybrana wartość jest brana pod uwagę...
Range - czyli zakres, wtedy system wypisze pole w stylu Cena od: [____] do: [____] - i analogicznie dobierze zapytanie które określi zakres (IMG:style_emoticons/default/smile.gif)

Tyle w teorii..

W praktyce wygląda to tak:

  1. CREATE TABLE IF NOT EXISTS `parametr` (
  2. `PRM_Id` int(11) NOT NULL AUTO_INCREMENT,
  3. `CAT_Id` int(11) NOT NULL,
  4. `PRM_Name` varchar(45) NOT NULL,
  5. `PRM_FormName` varchar(45) NOT NULL,
  6. `PRM_Type` enum('select','checkbox','range') NOT NULL,
  7. `PRM_MultiSelect` int(1) NOT NULL DEFAULT '0',
  8. `PRM_Value` text NOT NULL,
  9. `PRM_Sort` int(11) NOT NULL DEFAULT '0',
  10. `PRM_Active` tinyint(1) NOT NULL DEFAULT '1',
  11. PRIMARY KEY (`PRM_Id`),
  12. KEY `PARAMERTS` (`CAT_Id`,`PRM_Active`),
  13. KEY `PRM_FormName` (`PRM_FormName`)
  14. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;


Opis pól:
PRM_Id - id rekordu w tej tabeli
CAT_Id - id kategorii od której zaczyna się ten parametr (wszystkie kategorie dzieci będą dziedziczyć ten parametr)
PRM_Name - nazwa pola widzialna dla użytkownika: np. Kolor
PRM_FormName - nazwa pola w formularzu
PRM_Type - czyli to ten wybór z wspomnianych informacji powyżej...
PRM_MultiSelect - to nie jest potrzebne do tego zagadnienia (czyli można wywalić)
PRM_Value - tak samo (można pominąć)
PRM_Sort - kierunek sortowania (wartość liczbowa)
PRM_Active - wartość 1 jesli parametr aktywny i widoczny, 0 jeśli nieaktywny i niewidoczny


2 tabelą są wartości tych parametrów:
  1. CREATE TABLE IF NOT EXISTS `parametrvalue` (
  2. `PRV_Id` int(11) NOT NULL AUTO_INCREMENT,
  3. `PRM_Id` int(11) NOT NULL,
  4. `PRV_Value` varchar(255) NOT NULL,
  5. `PRV_Sort` int(11) NOT NULL DEFAULT '0',
  6. PRIMARY KEY (`PRV_Id`),
  7. KEY `parametr` (`PRM_Id`)
  8. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;


PRV_Id - id rekordu w tej tabeli
PRM_Id - id parametru (z poprzedniej tabeli)
PRV_Value - wartość widoczna dla użytkownika, np. Parametr Kolor, wartości: różowy, zielony, niebieski...
PRV_Sort - ustawienie kolejności sortowania (wartość liczbowa)


i ostatnia tabela z parametrami przypisanymi do samych produktów:

  1. CREATE TABLE IF NOT EXISTS `productsparametr` (
  2. `PRP_Id` int(11) NOT NULL AUTO_INCREMENT,
  3. `PRD_Id` int(11) NOT NULL,
  4. `PRV_Id` int(11) NOT NULL,
  5. `PRP_Value` varchar(45) NOT NULL,
  6. PRIMARY KEY (`PRP_Id`),
  7. KEY `PRODUCT` (`PRD_Id`),
  8. KEY `VALUE` (`PRV_Id`)
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


Opis pól:
PRP_Id - id rekordu
PRD_Id - id produktu
PRV_Id - id wartości (po tym dojdziecie jaki to parametr)
PRP_Value - wartość dla pola range (zakres)

To by było tyle jeśli chodzi o mój układ.
Napisanie samego zapytania chyba nie powinno stanowić problemu, w razie czego go tu wkleje...

Pozdo 600 i niech moc będzie z wami (IMG:style_emoticons/default/blinksmiley.gif)
Go to the top of the page
+Quote Post
lorak110786
post
Post #7





Grupa: Nieautoryzowani
Postów: 34
Pomógł: 1
Dołączył: 22.06.2009
Skąd: Koszalin/Poznań

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


@sniver
Mam bardzo podobny układ tabel. Prawie identyczny. Niemniej właśnie z zapytaniem mam problem. Mógłbyś się podzielić?
Go to the top of the page
+Quote Post
sniver
post
Post #8





Grupa: Zarejestrowani
Postów: 159
Pomógł: 5
Dołączył: 31.08.2007

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


Pomijając tabele z bazą produktów, cenami, promocjami itp. duperelami u mnie mniej więcej wygląda to tak:

To zapytanie liczące ilość produktów z wybranymi parametrami (wybrałem je bo jest krótsze, a długość o wiele mniejsza (IMG:style_emoticons/default/smile.gif) )

  1. SELECT
  2. ceil(count(0)/10) AS `licz`
  3.  
  4. FROM
  5. `products` AS `p`
  6. JOIN `productsparametr` AS `pp1` ON (`pp1`.`PRD_Id` = `p`.`PRD_Id`)
  7. JOIN `productsparametr` AS `pp2` ON (`pp2`.`PRD_Id` = `p`.`PRD_Id`)
  8. JOIN `productsparametr` AS `pp3` ON (`pp3`.`PRD_Id` = `p`.`PRD_Id`)
  9.  
  10. WHERE
  11. (`p`.`CAT_Id` IN (53))
  12. AND (`p`.`PRD_Deleted` = 0)
  13. AND (`p`.`PRD_Active` = 1)
  14. AND (
  15. (`pp1`.`PRV_Id` IN (48,49))
  16. AND (`pp1`.`PRP_Value` BETWEEN '3' AND '10')
  17. )
  18. AND (`pp2`.`PRV_Id` = 50)
  19. AND (`pp3`.`PRV_Id` IN (1,2,3))


każde podłączenie tabeli za pomocą join jest generowane przez skrypt php, co w konsekwencji buduje zapytanie sql. Zapytanie zostało wykonane ze strony: http://www.erobay.pl/kategorie/53/Biustonosze.html

więc możesz sobie zobaczyć względem parametrów jak sie to składa w całość (IMG:style_emoticons/default/smile.gif)

prawde mówiąc to troche sie napociłem by to wymyśleć i by działało, względem wyszukiwarki i kategorii w głąb. Oto mój sposób - może nie najlepszy i nie najbardziej efektywny ale działa ;]

PS. Nie wykorzystuje parametrów póki co, ale ten sposób napewno działa - poprostu parametry nie są przypisane do produktów (IMG:style_emoticons/default/biggrin.gif)

Ten post edytował sniver 7.10.2010, 13:10:04
Go to the top of the page
+Quote Post
lorak110786
post
Post #9





Grupa: Nieautoryzowani
Postów: 34
Pomógł: 1
Dołączył: 22.06.2009
Skąd: Koszalin/Poznań

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


@sniver
Zrobiłem tak jak u Ciebie. Buduję w ten sposób duże zapytanie. Zapytanie wykonuje się całkiem szybko a sposób jest nader skuteczny i przede wszystkim działa:)

  1. SELECT products.id_product, products.name, products.id_category, categories.value AS category, (
  2.  
  3. SELECT ROUND( MAX( price ) , 2 )
  4. FROM providers_products priceproviders
  5. WHERE products.id_product = priceproviders.id_product
  6. ) AS maxprice, (
  7.  
  8. SELECT ROUND( MIN( price ) , 2 )
  9. FROM providers_products priceproviders
  10. WHERE products.id_product = priceproviders.id_product
  11. ) AS minprice
  12. FROM products products
  13. JOIN treecat AS categories
  14. USING ( id_category )
  15. JOIN products_values AS param61
  16. USING ( id_product )
  17. JOIN products_values AS param63
  18. USING ( id_product )
  19. JOIN products_values AS param64
  20. USING ( id_product )
  21. WHERE products.id_category
  22. IN ( 115 )
  23. AND (
  24. param61.id_label = '61'
  25. AND param61.value
  26. BETWEEN 100
  27. AND 500
  28. )
  29. AND (
  30. param63.id_label = '63'
  31. AND param63.value
  32. BETWEEN 15
  33. AND 30
  34. )
  35. AND (
  36. param64.id_label = '64'
  37. AND param64.value
  38. IN ( 0, 1, 3 )
  39. )



Bardzo dziękuję Ci za pomoc. Serdecznie pozdrawiam:)
Go to the top of the page
+Quote Post
sniver
post
Post #10





Grupa: Zarejestrowani
Postów: 159
Pomógł: 5
Dołączył: 31.08.2007

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


nie ma za co - w takim razie myślę że ktoś może zamknąc (IMG:style_emoticons/default/haha.gif)
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 23.08.2025 - 07:40