Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> SELECT pola rodzica kategorii, dziedziczenie pola po rodzicu
Athlan
post 9.11.2010, 14:22:32
Post #1





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Witam,

posiadam tabelę 'categories':

-category_id int(11)
-category_parent int(11), default null
-category_price float(6,2), default null

Nie potrafię sobie poradzić z selectem, który wybierze kategorię o danym ID, a następnie sprawdzi cenę kategorii. Jeżeli cena nie została zdefiniowana (NULL), sprawdzi cenę rodzica category_parent, o ile został zdefiniowany. Jeżeli rodzic nie będzie miał ceny, sprawdzamy rodzica rodzica (dziadka). Aż do napotkania ceny lub rodzica, który nie ma rodzica, wówczas mamy NULL.

Drugie zapytanie jest analogiczne, ale chciałbym wyciągnąć nie tyle jeden rekord, co wszystkie, z ceną generowaną wg powyższej zasady.

Niestety, nie wiem w jaki sposób zapytać Google o takie rezultaty, zatem zapisałem posta. Jeżeli ktoś zechciałby się podzielić wiedzą - z góry wielkie dzięki, cisną mnie o to : )

Pozdrawiam serdecznie,
Athlan.


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 8)
phpion
post 9.11.2010, 14:36:53
Post #2





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Bez rekurencji się tutaj raczej nie obejdzie. Najlepiej napisać to jako funkcję w MySQL i przenieść ciężar pobierania danych na bazę danych.

Jeśli jednak znasz/możesz założyć maksymalne zagłębienie kategorii to możesz zrobić to 1 zwykłym zapytaniem JOINując n razy kolejno tą samą tabelę czyli coś na zasadzie:
  1. SELECT
  2. a.category_id AS category_id_1,
  3. a.category_price AS category_price_1,
  4.  
  5. b.category_id AS category_id_2,
  6. b.category_price AS category_price_2,
  7.  
  8. c.category_id AS category_id_3,
  9. c.category_price AS category_price_3
  10. -- itd...
  11. FROM
  12. categories AS a
  13. LEFT JOIN categories AS b ON (b.category_id = a.category_parent)
  14. LEFT JOIN categories AS c ON (c.category_id = b.category_parent)
  15. -- itd...

Oczywiście spowoduje to dokonanie nadmiernej ilości złączeń, no ale mówi się trudno.
Go to the top of the page
+Quote Post
Athlan
post 9.11.2010, 14:39:46
Post #3





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Problem polega na tym, że nie zakładam zagłębień kategorii, więc to rozwiązanie jest nie do zrobienia.

Oczywiście, można zapisywać poziom zagłębienia i sztucznie generować joiny, ale dla drugiego zapytania to nie zadziała.


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
phpion
post 9.11.2010, 14:47:13
Post #4





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Na pewno nie możesz założyć jakiegoś maksymalnego zagłębienia? Jeśli znalazłbyś taką liczbę (powiedzmy 5 - bo po co więcej zagłębień) to wówczas masz załatwione oba zapytania. W przypadku gdy liczba ta okaże się zbyt mała zwiększysz ją (np. w jakimś konfigu) i po sprawie.
Go to the top of the page
+Quote Post
Athlan
post 9.11.2010, 15:07:41
Post #5





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Wowczas problem bylby trywialny. Potrzebuje wyciagnac dane zgodnie ze schematem : )


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
phpion
post 9.11.2010, 15:37:11
Post #6





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




No to ostateczną cenę możesz wyciągnąć jako pierwsza wartość nie-NULL za pomocą COALESCE:
  1. SELECT
  2. a.category_id AS category_id_1,
  3. a.category_price AS category_price_1,
  4.  
  5. b.category_id AS category_id_2,
  6. b.category_price AS category_price_2,
  7.  
  8. c.category_id AS category_id_3,
  9. c.category_price AS category_price_3,
  10. -- itd...
  11.  
  12. COALESCE (category_price_1, category_price_2, category_price_3, ...) AS price
  13. FROM
  14. categories AS a
  15. LEFT JOIN categories AS b ON (b.category_id = a.category_parent)
  16. LEFT JOIN categories AS c ON (c.category_id = b.category_parent)
  17. -- itd...
Go to the top of the page
+Quote Post
Athlan
post 9.11.2010, 17:37:55
Post #7





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


@up: to już wiem, niektórzy programiści są tani i zaniżają rynek : ) Tanie rozwiązania są tańsze, uniwersalne są droższe.

Nie mogę użyć takiego rozwiązania. Muszę poradzić sobie rekurencją, natomiast nie wiem od jakiej strony to ugryźć.


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
zegarek84
post 9.11.2010, 18:51:21
Post #8





Grupa: Zarejestrowani
Postów: 1 332
Pomógł: 294
Dołączył: 12.10.2008
Skąd: Olkusz

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


jak już MySQL to w tej bazie masz coś takiego jak procedury - napisz sobie funkcję z wykorzystaniem while i przepisywaniem wartości do zmiennych:
http://maga.ovh.org/blog/?cat=8 - kliknij crlt+f i wklej "Jest również pętla WHILE"

MySQL Tutorial - Loop in Stored Procedures
są także REPEAT UNTIL oraz loop_label... a jeśli rozwiązać byś to chciał prosto w zwykłym sql, to o ile masz możliwość najprościej by było dopisać rekurencyjnie parametry drzewa nested tree z którego jednym zapytaniem możesz łańcuch rodziców...

a na wszelki wypadek jeszcze:
Variables in Stored Procedures

Ten post edytował zegarek84 9.11.2010, 18:52:05


--------------------
Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.

Go to the top of the page
+Quote Post
Athlan
post 9.11.2010, 20:05:11
Post #9





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Zrobiłem. Prowizorka:

  1. CREATE FUNCTION AnnouncementsCategoriesGetPrice(iCategoryId int(11)) RETURNS float(6,2)
  2. BEGIN
  3. DECLARE iResult FLOAT(6,2);
  4. DECLARE iPointer INT(11);
  5.  
  6. SET iPointer = iCategoryId;
  7. SET iResult = NULL;
  8.  
  9. WHILE (iPointer IS NOT NULL AND iPointer IS NOT NULL) DO
  10. SET iResult = (SELECT category_data_price FROM cms_announcements_categories WHERE category_id = iPointer);
  11. SET iPointer = (SELECT category_parent FROM cms_announcements_categories WHERE category_id = iPointer);
  12. END WHILE;
  13.  
  14. RETURN iResult;
  15. END


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
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: 14.08.2025 - 02:14