Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [MySQL] Optymalizacja zapytania
tadeurz
post
Post #1





Grupa: Zarejestrowani
Postów: 70
Pomógł: 1
Dołączył: 25.04.2009

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


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 ?


Ten post edytował tadeurz 31.05.2013, 23:30:51
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 6)
Talidali
post
Post #2





Grupa: Zarejestrowani
Postów: 79
Pomógł: 19
Dołączył: 31.05.2013

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


http://www.w3schools.com/sql/sql_union.asp


--------------------
Szukam pracy za granicą jako FrontendDeveloper - AKTUALNE

forum.php.pl/PoszukujePraca_Frontend_Developer_t218107.html
Go to the top of the page
+Quote Post
tadeurz
post
Post #3





Grupa: Zarejestrowani
Postów: 70
Pomógł: 1
Dołączył: 25.04.2009

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


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 ?

Ten post edytował tadeurz 1.06.2013, 01:06:50
Go to the top of the page
+Quote Post
pmir13
post
Post #4





Grupa: Zarejestrowani
Postów: 282
Pomógł: 89
Dołączył: 12.04.2011

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


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 ).

Ten post edytował pmir13 1.06.2013, 06:16:41
Go to the top of the page
+Quote Post
tadeurz
post
Post #5





Grupa: Zarejestrowani
Postów: 70
Pomógł: 1
Dołączył: 25.04.2009

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


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


Go to the top of the page
+Quote Post
bpskiba
post
Post #6





Grupa: Zarejestrowani
Postów: 340
Pomógł: 49
Dołączył: 3.07.2009
Skąd: Rzeszów

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


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
Go to the top of the page
+Quote Post
tadeurz
post
Post #7





Grupa: Zarejestrowani
Postów: 70
Pomógł: 1
Dołączył: 25.04.2009

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


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ź.


Ten post edytował tadeurz 1.06.2013, 13:22:38
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 Aktualny czas: 20.08.2025 - 14:26