laravel query intermediate table

0

Siema, SQL nigdy nie był i nie jest moja najlepsza strona, dlatego mam dla was pytanie

mam tabele users oraz **roles ** powiązane many-to-many, co w rezultacie daje pośredniczącą tabelę role_user

teraz chce znaleźć użytkowników którzy nie należą do danej roli, więc rozwiązałem to w ten sposób:

Pierw pobieram uzytkownikow którzy należą do podanej wczesniej roli

        $ids = DB::table('role_user')
                    ->where('role_id', $role->id)
                    ->pluck('user_id')
                    ->toArray();

Następnie szukam tylko tych, którzy nie znajdują się w powyższej tablicy

        $users = DB::table('users')
                    ->whereNotIn('id', $ids);

Oczywiście dostaje mój żądany wynik, ale
czy jest jakieś lepsze, szybsze,krótsze, bardziej czytelniejsze rozwiązanie?

1
SELECT `u`.*
FROM `users` AS `u`
JOIN `role_user` AS `r` ON `u`.`id` = `r`.`user_id`
WHERE `r`.`role_id` != "Twoja wykluczona rola"

A tak nie prościej? Przerzuć to sobie do tego eloquenta.

0

Pisane na telefonie, ale powinno działać.

$users = DB::table('users as u')
->join('role_user as ru', 'u.id', '=', 'ru.user_id'
->where('role_id', '!=', 'id wykluczonego')
->get();

Można też zdefiniować relację na modelu i wtedy wykorzystać eloquenta. Wyglądałoby to wtedy tak:

Users::with('roleUser')->where('user_id', '!=', 'wykluczone id')->get();

Tutaj można jeszcze użyć whereHas zamiast with jeżeli nie chcemy wyciągać danych z tabeli role_user a jedynie przefiltrować userów nią.

Tyle że pierw trzeba na modelach zdefiniować relacje, bo ten kod nie zadziała bez tego.

0
axelbest napisał(a):
SELECT `u`.*
FROM `users` AS `u`
JOIN `role_user` AS `r` ON `u`.`id` = `r`.`user_id`
WHERE `r`.`role_id` != "Twoja wykluczona rola"

A tak nie prościej? Przerzuć to sobie do tego eloquenta.

Czy to przypadkiem nie zwróci złych danych?
Załóżmy, że mamy role: admin, support, user i chcemy pobrać wszystkich, którzy nie są adminami.
User1 ma role: admin, user
User2 ma role: support, user
Czy Twoje zapytanie nie zwróci również User1? Bo co prawda nie jest on adminem, ale jest userem. I to znaczy, że w tabeli role_user rekord z rolą user spełnia warunek.

Dla przykładu, gdy chcemy zwrócić wszystkich adminów to można użyć (zakładając, że mamy zdefiniowane relacje w modelach):

$users = User::whereHas('roles', function ($query) {
            $query->whereIn('id', [1]); // gdzie 1 to id roli admina
        })->get();

Ale jeżeli chcemy zwrócić wszystkich oprócz adminów to zapytanie:

$users = User::whereHas('roles', function ($query) {
            $query->whereNotIn('id', [1]); // gdzie 1 to id roli admina
        })->get();

zwróci nieprawidłowe dane (gdy jakiś admin ma jeszcze inną rolę)

0

@up:
To jak zapytanie końcowo ma wyglądać zależy od potrzeb i struktury danych, a w głównym pytaniu nie było nic o tym, że ktoś może posiadać kilka ról.
W podanym przez Ciebie wypadku można np. zrobić selecta z użyciem where not in z zagnieżdżonym selectem wyciągającym id użytkowników z rolą admina. Wtedy pominie Ci wszystkich użytkowników z rolą admina, nawet jeżeli będą mieli inne role.

0
mefsh napisał(a):

@up:
To jak zapytanie końcowo ma wyglądać zależy od potrzeb i struktury danych, a w głównym pytaniu nie było nic o tym, że ktoś może posiadać kilka ról.
W podanym przez Ciebie wypadku można np. zrobić selecta z użyciem where not in z zagnieżdżonym selectem wyciągającym id użytkowników z rolą admina. Wtedy pominie Ci wszystkich użytkowników z rolą admina, nawet jeżeli będą mieli inne role.

Skoro autor powiazał użytkowników i role relację many-to-many to przyjąłem, że każdy user może może mieć wiele ról.

0

Tak, każdy user może mieć wiele ról, jak i jedna rola może mieć wielu userow

Użycie joina i where sprawdzało się gdy chciałem zdobyć userow którzy nalezą do xxx roli,
ale w druga stronę, gdzie chce dostać wszystkich oprócz tych co nalezą do yyy roli się już nie sprawdza

Działam na datatables i dostarczam dane w postaci kolekcji dlatego używam query zamiast eloquenta, Z reszta przy większych zapytaniach eloquent staje się nieczytelny, to co wrzuciłem to jedynie fragment całego zapytania które utworzyłem

wracając do mojego tematu, wczoraj zupełnie przypadkiem znalazłem twita
https://twitter.com/SOFTonSOFA/status/968503075836116992

w który gość wykonał prawie że identyczne zapytanie jak moje, więc wydaje mi się że takie źle nie jest :D

0

znowu ja, znowu problem z intermediate lub po prostu z laravelem

mam 2 zapytania, jedno napisane w prawie czystym sql, drugie pomieszane z laravelowskim selectsub

te zapytanie jest OK:

        $events = DB::table("events")
            ->select("events.*",
                DB::raw("(SELECT count(*) FROM event_user
                         WHERE event_user.event_id = events.id
                         ) as users"));

zwraca mi poprawny wynik, wszystko git ale, w

        $events = DB::table("events")
        ->select("events.*")
                        ->selectSub(function($query){
                $query->selectRaw("count(*)")
                        ->from("event_user")
                        ->where('event_user.event_id', '=', 'events.id');
            }, "users");

drugim przykładzie używam selectsuba i nie podlicza mi usersow... może go nie poprawnie używam? ciężko cokolwiek o nim przeczytać, nawet w dokumentacji nie ma przykładów z jego użyciem

relacje wiadome, tabela user, **event ** połączane many-to-many oraz pośrednicząca **event_user ** posiadająca id, event_id, user_id ( user_id to uczestnik imprezy, a nie założyciel)

1 użytkowników online, w tym zalogowanych: 0, gości: 1