Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Skompikowane zapytanie
Forum PHP.pl > Forum > Bazy danych > MySQL
Fallout
Witam,

Na początek podam ze strukturę bazy znajdziecie pod adresem: http://fallnet.sytes.net/siec-bud/export.jpg. Jesli chcecie poznac przykladowe dane to zapraszam pod adres: http://fallnet.sytes.net/siec-bud/index.php gdzie jest proste menu do wyswietlania danych z tabel co poznacie nizej winksmiley.jpg

Mam problem z sformułowaniem zapytania w sql`u. Sprawa wygląda mniej więcej tak:

Mam tabelę z nazwami cech (_cn), tablę z wartościami cech (_cw), tabelę z cechami przypisanymi do produktu (_cp) i tablę produkt (_prod). Strukturę i relacje znajdziecie w linku który podałem powyżej. Dla pewności zamieszczam sql`owe odpowiedniki:

  1. CREATE TABLE _prod (
  2. id_prod Int NOT NULL AUTO_INCREMENT,
  3. id_kat Float(0,0) NOT NULL,
  4. id_jm Int NOT NULL,
  5. PRIMARY KEY (id_prod)) TYPE = MyISAM
  6. ROW_FORMAT = DEFAULT;
  7.  
  8. CREATE TABLE _kat (
  9. id_kat Float(0,0) NOT NULL AUTO_INCREMENT,
  10. nk Varchar(20),
  11. kn Int NOT NULL,
  12. PRIMARY KEY (id_kat)) TYPE = MyISAM
  13. ROW_FORMAT = DEFAULT;
  14.  
  15. CREATE TABLE _jm (
  16. id_jm Int NOT NULL AUTO_INCREMENT,
  17. jm_skrot Varchar(20),
  18. jm_pelna_nazwa Varchar(20),
  19. PRIMARY KEY (id_jm)) TYPE = MyISAM
  20. ROW_FORMAT = DEFAULT;
  21.  
  22. CREATE TABLE _cn (
  23. id_cn Int NOT NULL AUTO_INCREMENT,
  24. cn Varchar(20),
  25. PRIMARY KEY (id_cn)) TYPE = MyISAM
  26. ROW_FORMAT = DEFAULT;
  27.  
  28. CREATE TABLE _cp (
  29. id_cp Int NOT NULL AUTO_INCREMENT,
  30. id_cw Int NOT NULL,
  31. id_prod Int NOT NULL,
  32. PRIMARY KEY (id_cp)) TYPE = MyISAM
  33. ROW_FORMAT = DEFAULT;
  34.  
  35. CREATE TABLE _cw (
  36. id_cw Int NOT NULL AUTO_INCREMENT,
  37. cw Varchar(20),
  38. id_cn Int NOT NULL,
  39. PRIMARY KEY (id_cw)) TYPE = MyISAM
  40. ROW_FORMAT = DEFAULT;



I wszystko było by w porządku, gdyby nie to, że każdy produkt ma WIELE cech. tzn:

Kod
"SELECT _kat.kn, _cw.cw, _jm.jm_skrot, FROM _kat, _cw, _jm, _cp WHERE _prod.id_prod=_cp.id_prod";
(to zapytanie moze byc nie poprawne) wyswietli mi wszystko za wyjatkiem tego ze podana bedzie jedna cecha (a dokladnie jej wartosc).....

czyli np:

|kategoria|nazwa|jednostka miary|

a (w zaleznosci od ilosci cech) chce otrzymac:

|kategoria|nazwa|model|typ|wysokosc|itp......|jednostka miary|

to chyba jest cos w stylu tabeli przestawnej? Kompletnie nie wiem jak to rozwiazac... nawet nie jestem pewien czy po prostu w samym php trzeba inaczej pobrac dane?

Z góry dziękuje za (p)odpowiedzi
pozdrawiam
Marcin

edit:

a jeszcze jedno.. troche poteoretyzuje.. czy przy takiej strukturze tabeli, bede mial mozliwosc rozroznienia produktu i jego cech .. tzn czy nie powinienem dodac jeszcze jedenej tabeli(encji) z _cp.id_cp i _prod.id_prod? Macie jakies sugestie?
popbart
Wnioskuję że chcesz otrzymać w jednym wierszu wszystkie cechy produktu.
Nie mogę się połapać w twoich "skrótach", więc spolszczam smile.gif
  1. SELECT kategoria.nazwa, group_concat(cechy.nazwa separator '|') AS cechy
  2. FROM kategoria INNER JOIN produkt ON (kategoria.id_kat=produkt.id_kat)
  3. INNER JOIN cechy_produktu ON (produkt.id_prod=cechy_produktu.id_prod)
  4. INNER JOIN cechy ON (cechy_produktu.id_cechy=cechy.id)
  5. GROUP BY produkt.id_prod
Fallout
Cytat(popbart @ 2005-02-11 01:32:57)
Wnioskuję że chcesz otrzymać w jednym wierszu wszystkie cechy produktu.
Nie mogę się połapać w twoich "skrótach", więc spolszczam smile.gif
  1. SELECT kategoria.nazwa, group_concat(cechy.nazwa separator '|') AS cechy
  2.  
  3. FROM kategoria INNER JOIN produkt ON (kategoria.id_kat=produkt.id_kat)
  4. INNER JOIN cechy_produktu ON (produkt.id_prod=cechy_produktu.id_prod)
  5. INNER JOIN cechy ON (cechy_produktu.id_cechy=cechy.id)
  6. GROUP BY produkt.id_prod

Niestety źle wywnioskowałeś winksmiley.jpg Kod mi jakoś nie chodzi ale to kwestia czasu smile.gif Ale poczytałem sobie w manualu sql`a i nie taki efekt chcem otrzymac.. twoj przykład robi mi 1 kolumne gdzie w wierszu bedzie takie cos: "cecha1|cecha2|itd.." a mi chodzi wlasnie o to aby kazda ta cecha byla w osobnej kolumnie...da sie tak zrobic?

pozdro i dzieki smile.gif

edit:

odkryłem czemu mi nie działa ta funkcja.. stary mysql.. smile.gif to dopiero w nowych wersajch (4.1.x) jest ja mam jeszcze 4.0.x ale zaraz nadrobie te zaleglosci smile.gif
popbart
Cytat
a mi chodzi wlasnie o to aby kazda ta cecha byla w osobnej kolumnie...da sie tak zrobic?

A po co ? (moim zdaniem się nie da)
W php robisz explode('|',$tablica['cecha']) i masz wszystko oddzielone smile.gif
FiDO
IMHO lepiej (wydajniej) jest zrobic 2 osobne zapytania. Mialem kilka dni temu akurat ten sam "problem", bo robilem maly sklepik na zaliczenie i tez mialem uniwersalne cechy. Info o produkcie pobieram w 2 zapytaniach, jedno pobiera info z tabeli produktow, a drugie wszystkie cechy (lacznie z ich nazwami z tabeli slownika cech).
Fallout
Cytat(popbart @ 2005-02-11 10:58:00)
A po co ? (moim zdaniem się nie da)
W php robisz explode('|',$tablica['cecha']) i masz wszystko oddzielone smile.gif

Ok.. to zrob mi na tym sortowanie, dodawanie i usuwanie oraz wyszukiwanie rekordow to cie złotem obsypie winksmiley.jpg Post powyzej pokazuje ze chyba jednak sie da tongue.gif

Cytat
IMHO lepiej (wydajniej) jest zrobic 2 osobne zapytania. Mialem kilka dni temu akurat ten sam "problem", bo robilem maly sklepik na zaliczenie i tez mialem uniwersalne cechy. Info o produkcie pobieram w 2 zapytaniach, jedno pobiera info z tabeli produktow, a drugie wszystkie cechy (lacznie z ich nazwami z tabeli slownika cech).


A byłbyś taki miły i wkleił przykładowy kod? Ja juz sobie go przerobie odpowiednio smile.gif
popbart
Cytat
Post powyzej pokazuje ze chyba jednak sie da

Co się da!? Przecież chciałeś mieć to w osobnych kolumnach(jednym zapytaniem) a on robi dwa zapytania
Cytat
Ok.. to zrob mi na tym sortowanie, dodawanie i usuwanie oraz wyszukiwanie rekordow to cie złotem obsypie

Jak byś używał postgresa to by nie było problemu: robisz podzapytanie from( i tu dajesz zwykłego select'a łączącego z sortowaniem). A tak chcesz robić zaawansowane żeczy na prymitywnej bazie. Można zrobić coś takiego: group_concat(cechy.nazwa order by cechy.nazwa separator '|') ale to tylko sortuje wewnetrzne cechy produktu
Wyszukiwanie ? A co za problem dać odpowiedni where ?
W dodawaniu lub edytowaniu pewnie nie obędzie się bez dwóch zapytań, ale wtedy operujesz tylko na jednym produktcie i to zupełnie inny select.
Cytat
Info o produkcie pobieram w 2 zapytaniach, jedno pobiera info z tabeli produktow, a drugie wszystkie cechy (lacznie z ich nazwami z tabeli slownika cech)

A jak chcesz wyświetlić 50 produktów, to co, robisz 51 zapytań?
Fallout
Cytat(popbart @ 2005-02-11 18:58:17)
1)
Co się da!? Przecież chciałeś mieć to w osobnych kolumnach(jednym zapytaniem) a on robi dwa zapytania
2)
Jak byś używał postgresa to by nie było problemu: robisz podzapytanie from( i tu dajesz zwykłego select'a łączącego z  sortowaniem). A tak chcesz robić zaawansowane żeczy na prymitywnej bazie. Można zrobić coś takiego: group_concat(cechy.nazwa order by cechy.nazwa separator '|') ale to tylko sortuje wewnetrzne cechy produktu
Wyszukiwanie ? A co za problem dać odpowiedni where ?
W dodawaniu lub edytowaniu pewnie nie obędzie się bez dwóch zapytań, ale wtedy operujesz tylko na jednym produktcie i to zupełnie inny select.

1) A wiec tak w manualu czytamy..."This function returns a string result with the concatenated non-NULL values from a group" czyli mi tworzy kolumne np. cechy i jako wartosc sumuje je w lancuch z rozdzielnikiem np % czy | ... a właśnie tu jest pies pogrzebany aby te CECHY były KOLUMNAMI . Wiec jak widzisz nie o to mi chodzilo....

2) Nie bede dostosowywal serwera baz do bazy bo to mija sie z sensem.. to baza ma sie dostosowac.. nie bede przeciez instalowal nowego serwera SQL pod jedna baze...
FiDO
Cytat
A jak chcesz wyświetlić 50 produktów, to co, robisz 51 zapytań?


Nie mam potrzeby wyswietlania naraz wielu produktow i cech do nich. Po wybraniu kategorii wyswietlam podstawowe info o produkcie z tabeli z produktami, a po kliknieciu na produkt wyswietla sie juz jego szczegolowy opis ze wszystkimi danymi z tabeli produktow oraz cechami.

@Fallout: poszlo na PM
popbart
Cytat
2) Nie bede dostosowywal serwera baz do bazy bo to mija sie z sensem.. to baza ma sie dostosowac.. nie bede przeciez instalowal nowego serwera SQL pod jedna baze...

W twoim przypadku to aplikacja się dastosuje do serwera (bedzie robiła masę selectów i życzę jej powodzenia) smile.gif
Inwestycja w PostgreSQL będzie owocowała nie tylko w tej bazie, jeszcze dojdziesz do takiego wniosku winksmiley.jpg
A tak w ogóle to jest tylko problem z sortowaniem bo w wyszukiwaniu nie ma problemu (polecenie where wykonuje się przed group by)
Pozdrawiam,
Bartek P
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.