Lekcja dla chętnych, na przykładzie z poprzedniej lekcji wykorzystamy okazję, aby poznać zmienne w SQL. Do dzieła.
Ok, poprzednio napisaliśmy taką komendę:
Artisan::command('review-min-rating-2', function () {
$min = Review::min('rating');
$numberOfMinReviews = Review::where('rating', $min)->count();
$this->comment("Minimum rating: {$min}");
$this->comment("Number of reviews with minimal rating: {$numberOfMinReviews }");
});
Mamy tu ewidentnie dwie operacje:
- Pobranie minimalnej (najmniejszej oceny) i zapisanie do zmiennej
- Policzenie ilości recenzji, gdzie ocena jest taka, jak ta zmienna (czyli minimalna)
Wytłumaczyliśmy to sobie, całkiem logicznie, że działa to jak mini-select (pobierz najmniejszą ocenę) w większym selekcie (podlicz oceny gdzie ocena to mały select).
I idąc tą logiką napisaliśmy coś takiego:
SELECT COUNT(rating)
from `reviews`
where rating = (SELECT min(rating) from `reviews`);
Problem z tym rozwiązaniem jest taki, że o ile nie zastosowali (twórcy SQLa) jakiejś optymalizacji, która w jakiś sposób wykrywa, że nam ten select (subquery) potrzebny jest tylko raz, to wygląda na to, że chodzi on za każdym selectem-rodzicem.
Ok, może to nie jest najlepszy przykład, jeszcze zobaczymy lepsze subqueries.
Poza tym – chcemy poznać tyle SQLa, ile to możliwe. Więc sprawdźmy, czy jest coś takiego jak zmienne w SQL.
Ok, zróbmy taką komendę:
SELECT @min_rating := min(rating) from `reviews`;
Btw to jest walrus operator, znany z Pythona i kilku innych języków. Wygląda na to, że zmienna zaciągnięta, wartość to 1.
Użyjmy jej:
SELECT count(*) from `reviews` where rating = @min_rating;
Nic nie mamy. Bo zmienne się nie zapisują. Musimy wrzucić 2 queries na raz:
SELECT @min_rating := min(rating) from `reviews`;
SELECT count(*)
from `reviews`
where rating = @min_rating;
I działa, dostaniemy dwa wyniki, jeden po drugim, pierwszy to wartość zmiennej, drugi to podliczone recenzje z minimalną oceną.
Możemy też bawić się w stored procedures, ale tego jeszcze nie znamy. Niemniej warto wiedzieć, że zmienne w SQLu istnieją, podobnie subrutyny.