Jestem nowicjuszem w MySQL i dzięki wsparciu ze strony bardziej doświadczonych użytkowników jestem w stanie sobie z tym poradzić, jednocześnie dużo się ucząc.Jak mogę uprościć/poprawić wydajność tego zapytania MySQL?
Mam zapytanie, które robi dokładnie to, co chcę. Jednak dla mnie wygląda to bardzo niechlujnie i jestem pewien, że musi istnieć sposób, aby to uprościć.
W jaki sposób można poprawić i zoptymalizować to zapytanie pod kątem wydajności?
Dziękujemy
$sQuery = "
SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns))."
FROM $sTable b
LEFT JOIN (
SELECT COUNT(*) AS projects_count, a.songs_id
FROM $sTable2 a
GROUP BY a.songs_id
) bb ON bb.songs_id = b.songsID
LEFT JOIN (
SELECT AVG(rating) AS rating, COUNT(rating) AS ratings_count, c.songid
FROM $sTable3 c
GROUP BY c.songid
) bbb ON bbb.songid = b.songsID
LEFT JOIN (
SELECT c.songid, c.userid,
CASE WHEN EXISTS
(
SELECT songid
FROM $sTable3
WHERE songid = c.songid
) Then 'User Voted'
else
(
'Not Voted'
)
end
AS voted
FROM $sTable3 c
WHERE c.userid = $userid
GROUP BY c.songid
) bbbb ON bbbb.songid = b.songsID
EDIT: Tutaj znajduje się opis tego, co kwerenda robi: -
Mam trzy tabele:
$ stabilny = stół piosenek (songid, mp3link, grafika, useruploadid itp.)
$ sTable2 = tabelę projektów z piosenkami z nimi związanych (ProjectID, songid, nazwa projektu itd.)
$ sTable3 = tabelę ocen Song (songid, userid, ocena)
Wszystkie te dane są wysyłane do tablicy JSON i wyświetlane w tabeli w mojej aplikacji, aby zapewnić listę utworów w połączeniu z danymi projektów i ocen.
Sama kwerenda wykonuje następujące czynności w następującej kolejności: -
- Zbiera wszystkie wiersze z $ stabilny
- dołącza do $ sTable2 na songsID i zlicza liczbę wierszy (projektów) w tej tabeli, które mają samo songsID
- dołącza do $ stable3 na songsID i pracuje się średnio w kolumnie „Ocena” w tej tabeli, które mają taką samą songsID
- w tym momencie również zlicza całkowitą liczbę wierszy w $ sTable3 które ten sam identyfikator utworu, aby zapewnić całkowitą liczbę głosów .
- W końcu sprawdza wszystkie te wiersze, aby sprawdzić, czy identyfikator $ userid (który jest zmienną zawierającą identyfikator zalogowanego użytkownika) odpowiada sklepom "userid" w $ sTable3 dla każdego wiersza, aby sprawdzić, czy użytkownik już głosował na dany songID lub nie. Jeśli się zgadza, zwraca "Użytkownik zagłosował", jeśli nie zwraca "Nie zagłosowano". Wyświetla to jako oddzielną kolumnę w mojej tablicy JSON, którą następnie sprawdzam w aplikacji i dodam klasę do klienta.
Jeśli potrzebujesz więcej informacji, daj mi znać. Dziękuje wszystkim.
EDIT:
Dzięki Aurimis' doskonałej pierwszej próbie jestem zbliża się o wiele bardziej proste rozwiązanie.
To jest kod, który próbowałem na podstawie tej sugestii.
SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns))."
FROM
(SELECT
$sTable.songsID, COUNT(rating) AS ratings_count,
AVG(rating) AS ratings
FROM $sTable
LEFT JOIN $sTable2 ON $sTable.songsID = $sTable2.songs_id
LEFT JOIN $sTable3 ON $sTable.songsID = $sTable3.songid
GROUP BY $sTable.songsID) AS A
LEFT JOIN $sTable3 AS B ON A.songsID = B.songid AND B.userid = $userid
Istnieje jednak kilka problemów. Musiałem usunąć pierwszą linię odpowiedź gdyż spowodował błąd 500 serwera wewnętrznego:
IF(B.userid = NULL, "Not voted", "User Voted") AS voted
Oczywiście teraz „głosowało check” funkcjonalność jest stracone.
Co więcej, nie zwraca wszystkich kolumn zdefiniowanych w mojej tablicy, tylko identyfikator utworu. Mój JSON zwraca nieznaną kolumnę "nazwa_piosenki" w "liście pól" - jeśli usuniemy ją z mojej tablicy $ aColumns, przejdzie ona oczywiście do następnej.
Definiuję moje kolumny na początku mojego skryptu, ponieważ ta tablica służy do filtrowania i zestawiania danych wyjściowych dla kodowania JSON. Jest to definicja $ aColumns: -.
$aColumns = array('songsID', 'song_name', 'artist_band_name', 'author', 'song_artwork', 'song_file', 'genre', 'song_description', 'uploaded_time', 'emotion', 'tempo', 'user', 'happiness', 'instruments', 'similar_artists', 'play_count', 'projects_count', 'rating', 'ratings_count', 'voted');
W celu szybkiego sprawdzenia resztę zapytania I zmodyfikowaną pierwszą linię w podzapytaniu wybierz $ stabilny * zamiast $ sTable.songsID (pamiętaj $ stabilny jest tabelą piosenek)
Następnie ... Zapytanie oczywiście zadziałało, ale z fatalną wydajnością oczywiście. Ale tylko zwróciło 24 utwory z zestawu 5000 utworów testowych. Dlatego zmieniłem twoje pierwsze "JOIN" na "LEFT JOIN", aby wszystkie 5000 piosenek zostało zwróconych. Aby wyjaśnić zapytanie, należy zwrócić WSZYSTKIE wiersze w tabeli utworów, ale z różnymi dodatkowymi bitami danych z tabel projektów i ocen dla każdej piosenki.
Tak więc ... Docieramy i jestem pewien, że jest to o wiele lepsze podejście, które wymaga jedynie pewnych modyfikacji. Dzięki za pomoc do tej pory Aurimis.
wydaje się, że osoba, która napisała zapytanie nie był nowy do MySQL – newtover
napisałem go samodzielnie przez „googlowania”, pytając różne pytania tutaj i czytania dużo. Mam jednak w istocie powiązanie kilku elementów w jedno "działające" zapytanie, aby osiągnąć to, czego chcę. Chociaż rozumiem, co robi każda część zapytania i dlaczego działa, nie mam doświadczenia, aby wiedzieć, czy robię to w skuteczny sposób, czy też nie. Mój instynkt z mojego doświadczenia z innymi językami mówi mi, że nie jestem. Dlatego z radością powitam rady bardziej doświadczonych programistów MySQL. :) – gordyr
Czy możesz opisać oczekiwany rezultat? – Peter