brymen
31.10.2016, 18:28:13
Witam,
Mam trzy tabele
op,
rem,
users. Zapytanie zwraca mi wyniki z tabeli
op oraz z tabeli
rem podczepia mi id użytkowników. Potrzebuję jeszcze translatora id na name z 3 tabeli
users. Jakaś podpowiedź?
SELECT `op1`.`id` AS id_op, GROUP_CONCAT(`op2`.`id`) AS `id_user` FROM `op` AS `op1` LEFT JOIN `rem` AS `op2` ON `op1`.`id` = `op2`.`id_wt` WHERE `op1`.`id` = 284
Wynik zapytania z brakującym elementem

id_op | id_user | name
284 | 174,324 |

Dziękuję za pomoc.
SmokAnalog
31.10.2016, 18:33:31
Musisz zrobić jeszcze jeden JOIN.
brymen
31.10.2016, 18:44:06
Próbowałem, jednak mi nie wychodzi, dlatego pytam. Zrobiłem podzapytanie na początku SELECTa bez dodatkowego JOINa i nawet działa ale jak mi sprawdza tabele które mają po 30tys rekordów to trwa to ok 5s, zdecydowanie za długo. Dlatego chciałbym zamienić to na JOINa.
SmokAnalog
31.10.2016, 18:48:07
Pokaż tego swojego JOIN-a to Ci powiem dlaczego Ci nie działa.
brymen
31.10.2016, 19:04:39
Próbowałem kilku sposobów ale raczej kupy się to nie trzyma.
Kod
SELECT `op1`.`id`, GROUP_CONCAT(`rem1`.`id`) AS `id_user`, GROUP_CONCAT(`users1`.`name`) AS `name` FROM `op` AS `op1`
LEFT JOIN `rem` AS `rem1` ON `rem1`.`id_wt` = `op1`.`id`
LEFT JOIN `users` AS `users1` ON `users1`.id IN (GROUP_CONCAT(`rem1`.`id`))
lub wersja z podzapytaniem po JOIN
Kod
[sql]SELECT `op1`.`id`, GROUP_CONCAT(`rem1`.`id`) AS `id_user`, GROUP_CONCAT(`users1`.`name`) AS `name` FROM `op` AS `op1`
LEFT JOIN `rem` AS `rem1` ON `rem1`.`id_wt` = `op1`.`id`
LEFT JOIN (SELECT `name` AS `usr` FROM `users`) AS `hh` ON `hh`.`id` IN (GROUP_CONCAT(`rem1`.`id`)[/sql]
trueblue
31.10.2016, 19:30:28
Trzeci LEFT JOIN ma łączyć pojedyncze wartości pól, czyli tam bez żadnego GROUP_CONCAT.
Sprawdź czy masz pozakładane indeksy na łączone pola, albo relacje w przypadku tabel typu InnoDB.
brymen
31.10.2016, 19:41:33
W trzecim LEFT JOIN faktycznie się rozpędziłem ale to nie zmienia faktu, że i tak nie działa. Indeksy mam na wszystkie wymagane kolumny jednak tylko pojedyncze. Łączone mogą znacząco przyspieszyć?
trueblue
31.10.2016, 20:08:09
Pokaż zapytanie ostateczne.
Co to znaczy, że nie działa?
Indeks powinien być założony tam gdzie zachodzą porównania (WHERE, JOIN).
brymen
31.10.2016, 20:31:08
Działające zapytanie, które chciałbym przepisać na JOIN bez podzapytania.
SELECT `op1`.`id`,(SELECT GROUP_CONCAT(`us`.`name`) FROM `users` AS `us` LEFT JOIN `rem` ON `us`.`id` = `rem`.`id_user` WHERE (`op1`.`id` = `rem`.`id_wt`) AND `us`.`id` IN (SELECT `id_user` FROM `rem` AS `r` WHERE `r`.`id_wt` = `op1`.`id`)) AS `usr` FROM `op` AS `op1`
trueblue
31.10.2016, 20:40:56
Myślałem, że wrócisz do dwóch LEFT JOIN.
Może bez aliasów tabel będzie czytelniej:
SELECT op.id, GROUP_CONCAT(rem.id) AS id_user, GROUP_CONCAT(users.name) AS name
FROM op
LEFT JOIN rem ON rem.id_wt = op.id
LEFT JOIN users ON users.id=rem.id
WHERE op.id = 284
Dlaczego to zapytanie daje niepoprawny wynik?
brymen
31.10.2016, 20:56:12
Błąd znaleziony, moja wina. Nie wiem dlaczego w tabeli users brakowało id które były w tabeli rem, nie sprawdzając tego uznałem, że mam błąd w zapytaniu.
Dziękuję za pomoc.
trueblue
31.10.2016, 20:58:05
A zgrupowane name masz w takiej kolejności jak odpowiadające im zgrupowane id?
brymen
1.11.2016, 08:12:00
Tak, kolejność name pokrywa się z id ale dla mnie nie ma to już większego znaczenia. Teraz muszę sprawdzić czy całe zapytanie wykona się szybciej. Muszę jeszcze pomyśleć nad grupowymi indeksami, wcześniej nie brałem tego pod uwagę, ustawiłem pojedyncze i wszystko śmigało. Baza zaczęła się przytykać więc czas na optymalizację.
To może jeszcze mała podpowiedź. Zapytanie poniżej działa idealnie z WHERE ale potrzebowałbym wyświetlić cała tabelę z LEFT JOIN. Bez warunku podstawia mi wszystko do jednego pierwszego wiersza. Widać, że GROUP_CONCAT blokuje.
Kod
SELECT op.id, GROUP_CONCAT(rem.id) AS id_user, GROUP_CONCAT(users.name) AS name
FROM op
LEFT JOIN rem ON rem.id_wt = op.id
LEFT JOIN users ON users.id=rem.id
WHERE op.id = 284
trueblue
1.11.2016, 08:37:58
GROUP BY op.id zamiast WHERE.
brymen
1.11.2016, 08:54:36
Zamiana podzapytania na LEFT JOIN nie przyspieszyło działania. Znalazłem jednak dokładna przyczynę. Poniższy kod wykonuje się prawidłowo, jednak bardzo długo ok 5s. Przyczyną jest dodatkowy warunek w środkowym LEFT JOIN
Kod
OR `rem`.`id_wt` = `event2`.`id
.
Mała legenda:
`mark` - kolumna grupująca
`link_id` - kolumna łącząca
`id_wt` = id z tabeli op
SELECT `event`.`id`, GROUP_CONCAT(`users`.`email`) AS `user_ack` FROM `event` AS `event1`
LEFT JOIN `event` AS `event2` ON `event2`.`mark` = `event1`.`link_id` AND `event2`.`id` = (SELECT MAX(`id`) FROM `event` WHERE `mark` = `event1`.`link_id`)
LEFT JOIN `rem` ON `rem`.`id_wt` = `event1`.`id` OR `rem`.`id_wt` = `event2`.`id`
LEFT JOIN `users` ON `users`.`id` = `rem`.`id_user`
WHERE `event1`.`id` IN (SELECT MAX(`id`) FROM `event` GROUP BY `mark`) GROUP BY `event1`.`id`
Ma ktoś pomysł jak to lepiej napisać?
SmokAnalog
1.11.2016, 23:19:03
Zacznij od zmiany nazw tabel i kolumn jeśli to możliwe. Żadnych op, op1, zn, bo aż się nie chce tego czytać.
brymen
2.11.2016, 08:03:23
Poprawiłem nazwy kolumn, jednak nie mam pewności czy teraz jest bardziej czytelne. Aliasy event1, event2 musiały pozostać, bez tego query prawidłowo nie zadziała (chyba).
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.