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.