Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL] Optymalizacja zapytania
Forum PHP.pl > Forum > Bazy danych > MySQL
tadeurz
Mam mały problem z zapytaniem.
Mam tabelki:
board_topic -> id,id_autora_tematu,id_autora_ostaniego_posta
user -> id,name

Nazwy są intuicyjne, mimo tego wyjaśnię:
Pierwsza przechowuje id tematu, id użytkownika który założył temat, i id użytkownika który jako ostatni wypowiedział się w temacie.
Problem pojawia się kiedy chce pobrać 20 rekordów. Wykombinowałem to tak:
  1. SELECT board_topic.topic ,user.name
  2. FROM board_topic
  3. LEFT JOIN user ON user.id = board_topic.id_autora_tematu OR user.id = board_topic.id_autora_ostaniego_posta
  4. LIMIT 20
  5. // wynik
  6. 1. Przykładowy temat numer 1 | Michał //autor tematu
  7. 2. Przykładowy temat numer 1 | Maciek //autor ostatniego postu
  8. 3. Przykładowy temat numer 2 | Monika //autor tematu
  9. 4. Przykładowy temat numer 2 | Maciek //autor ostatniego postu

Jak widać każdy z tematów występuje 2 razy, i jest to zrozumiałe -> tak skonstruowane jest zapytanie.
Jest jakiś inny sposób aby złączyć tabele w sposób: jednemu rekordowi z jednej dołączamy 2 z innej tabeli ?

//----------------------------------------------
Coś nie daję rady z tym SQL dzisiaj biggrin.gif
Mam tabele z tematami -> które podzieliłem na kategorię. I chce pobrać po 20 rekordów z każdej.
  1. SELECT * FROM board_topic WHERE category =`help` LIMIT 20
  2. SELECT * FROM board_topic WHERE category = `question` LIMIT 20
  3. SELECT * FROM board_topic WHERE category = `question` LIMIT 20


Oczywiście mogę to zrobić jak wyżej z 3 SELECT wykorzystując multipleQuery. Ale da się to zrobić lepiej ? optymalniej ? może w 1 zapytaniu ?
Talidali
http://www.w3schools.com/sql/sql_union.asp
tadeurz
facepalmxd.gif
To drugie mamy rozwiązane. biggrin.gif

UNION jest też odpwiedzą na 1 problem ? bo jeśli tak to nie mogę załapać. Some tip, please ?
pmir13
Nie widzę przeszkód by łączyć dwukrotnie do tej samej tabeli (pod innymi aliasami), za pierwszym razem by dostać dane autora, za drugim by dostać dane ostatniego wypowiadającego się w temacie.
Wtedy limit 20 będzie dotyczył pojedyńczych tematów.
Poza tym, jeśli w każdym temacie oba pola są wypełnione (jeśli nikt nie odpowiedział to post startowy traktujemy jako ostatni, więc oba id są identyczne), a użytkownicy nie są kasowani ani nie zmieniają id, to nie jest potrzebny LEFT JOIN, wystarczy zwykły JOIN ( czyli INNER JOIN precyzyjnie ujmując ).
tadeurz
Nie wiedziałem że konstrukcja JOIN pozwala na takie coś. W kursach nigdy się z takim czymś nie spotkałem.

Dla podsumowania wklejam ostateczne zapytanie. Jakby ktoś miał jeszcze jakąś sugestię pozwalającą to ulepszyć to proszę bardzo.
  1. SELECT board_topic.topic ,start.name,last.name
  2. FROM board_topic
  3. JOIN user AS start ON start.id = board_topic.id_autora_tematu
  4. JOIN user AS last ON last.id = board_topic.id_autora_ostaniego_posta
  5. category =`help`
  6. LIMIT 20
  7. UNION
  8. SELECT board_topic.topic ,start.name,last.name
  9. FROM board_topic
  10. JOIN user AS start ON start.id = board_topic.id_autora_tematu
  11. JOIN user AS last ON last.id = board_topic.id_autora_ostaniego_posta
  12. category =`question`
  13. LIMIT 20


bpskiba
a tak może być questionmark.gif
  1. SELECT board_topic.topic ,start.name,last.name
  2. FROM board_topic
  3. JOIN user AS start ON start.id = board_topic.id_autora_tematu
  4. LEFT JOIN user AS last ON last.id = board_topic.id_autora_ostaniego_posta
  5. WHERE
  6. category =`help` OR category =`question`
  7. LIMIT 20
tadeurz
bpskiba nie może tak być.
Ja chce pobrać po 20 z każdek kategorii. 20 z help i 20 z question.
/--------
Dodam tylko że jestem świadomy innego rozwiązania:
W oryginalnym skrypcie oczywiście znajduje się jeszcze jedna tabela:
  1. Board_post -> id_postu, id_tematu, id_autora, id_data_postu


Można by w tabeli board_topic zamiast id_autorów przechowywać id_pierwszego postu oraz id_ostatniego postu. I JOIN’nować koleją tabelę -> board_post. W takiej sytuacji nie dublowałbym tych samych danych (id_autorów, datę_postów).
Wolę świadomie zwiększyć wielkość bazy danych niż obciążać ją bardziej złożonymi zapytaniami. To rozwiązanie wydaje się optymalniejsze, jeżeli się mylę proszę o odpowiedź.
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.