Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Sortowanie i asc / desc w klauzuli IF lub CASE
Forum PHP.pl > Forum > Bazy danych > MySQL
foo.noob
Witam.

Mam takie oto zapytanie w serwisie blogowym:

SELECT `Comment`.`id`, `Comment`.`parent_id`, `Comment`.`comment`, `Comment`.`created`, FROM `comments` AS `Comment` WHERE `post_id` = 1 AND `visible` = 1
ORDER BY created asc

Zapytanie to wyciąga komentarze przypisane do danego postu. Komentarze mogą być zagnieżdżone, tj. użytkownicy mogą umieścić odpowiedź do danego komentarza (stąd pole 'parent_id').

Problem polega na tym, że użytkownicy mają możliwość ustawienia sobie sortowania listy komentarzy, między asc i desc.
W przypadku sortowania asc jest wszystko OK, natomiast jeśli chodzi o sortowanie desc - czyli przypadek gdzie najnowsze komentarze wyświetlane są na początku - wyniki zapytania, poprzez sortowanie desc, wyglądają tak, że odpowiedź na dany komentarz, umieszczona później niż inna odpowiedź na ten sam komentarz - wyświetla się jako pierwsza.

Chciałam to zmodyfikować - tak aby w przypadku sortowania komentarzy po dacie malejąco - komentarze będące odpowiedzią (czyli z polem parent_id różnym od NULL) sortowały się w sposób rosnący (czyli najnowsze odpowiedzi na końcu listy odpowiedzi na dany komentarz).

Spróbowałam umieścić klauzulę IF w ORDER BY następująco:

SELECT `Comment`.`id`, `Comment`.`parent_id`, `Comment`.`comment`, `Comment`.`created`, FROM `comments` AS `Comment` WHERE `post_id` = 1 AND `visible` = 1
ORDER BY IF parent_id IS NULL THEN created desc ELSE created asc END

czyli - w przypadku gdy parent_id jest nullem (komentarz nie jest odpowiedzią) ma się sortować malejąco, ale w innym przypadku (gdy komentarz jest odpowiedzią) - ma się sortować rosnąco.

Niestety w wyniku tego zapytania otrzymałam błąd:
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'parent_id IS NULL THEN created desc ELSE created asc END' at line 1

Gdzieś wyczytałam, że klauzuli ASC i DESC nie można używać w IFie czy CASE'ie.
Jaki może być sposób na obejście tego problemu?
Z góry dziękuję za pomoc:)
Sephirus
Po pierwsze używaj BBCode daj SQL w nawiasy [] jeśli potrzebujesz pisać kod SQL.

Po drugie użycie IF itp w ORDER odpada - tak jak pisałeś.

Jeśli dobrze Cię zrozumiałem chcesz uzyskać takie coś:

K - komentarz
O - odpowiedź

ASC:

K1
O1
O2
K2
O1
O2

DESC:

K2
O1
O2
K1
O1
O2

questionmark.gif

Jednym zapytaniem tego nie osiągniesz bo to zaburza idee sortowania. Masz dwie opcje

1. Pobierać same komentarze główne (parent_id = NULL) i dobierać do każdego odpowiedzi sortowane po ASC

2. Zmienić obsługę w PHP dla DESC. Przejechać po całej tablicy wyników. Najpierw użyj array_reverse by dostać wyniki tak jak dla ASC. Potem iterując po niej utwórz nową tablicę, w której będziesz dodawał w pierwszym poziomie komentarze główne a do nich (drugi poziom) będziesz dopisywał odpowiedzi. Na tej tablicy znów daj array_reverse i wyświetl ją. Przy każdym komentarzu zatrzymaj się i wyświetl odpowiedzi. W ten sposób dostaniesz sortowanie DESC głównych komentarzy i ASC odpowiedzi do nich przypisanych (tak jak być powinno). Tyle zamieszania w to wmieszałem ze względu na to, że na pewno będziesz chciał udostępnić możliwość stronicowania - a przy tej metodzie przejdzie ona bez żadnych problemów
foo.noob
Cytat(Sephirus @ 26.11.2012, 12:53:07 ) *
Jeśli dobrze Cię zrozumiałem chcesz uzyskać takie coś:

K - komentarz
O - odpowiedź

ASC:

K1
O1
O2
K2
O1
O2

DESC:

K2
O1
O2
K1
O1
O2

questionmark.gif

Tak, dokładnie coś takiego chcę uzyskać.
Problem w tym, że odpowiedzi mogą być zagineżdżone o więcej niż jeden stopień. Czyli może być np. odpowiedź do odpowiedzi i tak dalej, W związku z tym potrzebna mi była jakaś generalna funkcja, bez definiowania stopnia zagnieżdżenia.
Dodatkowy sęk to taki, że sama aplikacja jest zbudowana przy użyciu frameworka CakePHP i korzysta z wbudowanego behaviora Tree. Dzięki temu jedno zapytanie wyławia wszystkie komentarze z zagnieżdżonymi odpowiedziami według schematu:
  1. Array
  2. (
  3. [0] => Array
  4. (
  5. [Comment.id] => X
  6. [Comment.parent_id] => X
  7. [Comment.comment] => X
  8. [Comment.created] => X
  9. [children] => Array
  10. (
  11. [0] => Array
  12. (
  13. [Comment.id] => X
  14. [Comment.parent_id] => X
  15. [Comment.comment] => X
  16. [Comment.created] => X
  17. )
  18. )
  19. )
  20. )

gdzie w tablicy o indeksie 'children' przechowywane są zagnieżdżone komentarze (odpowiedzi).

Rozwiązałam to następująco:
- dla ASC zapytanie pozostaje takie jak jest, gdyż nie generuje to problemu sortowania odpowiedzi
- dla DESC - robię zapytanie z sortowaniem ASC, a następnie array_reverse na wyniku - dzięki czemu kolejność tylko komentarzy głównych ulega zmianie w taki sposób, jakby były posortowane DESC

W każdym razie - dzięki za pomoc:)
mmmmmmm
Pokaż przykładowe dane IN i OUT - pewnie da się to zrobić jednym zapytaniem. (znaczy się pewnie ja to umiem smile.gif )
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.