Klauzula HAVING

 

Język SQL dostarcza jeszcze jedną metodę filtrowania wyników zapytań — jeżeli grupujemy wyniki (a więc używamy klauzuli GROUP BY), możemy sprawdzić, czy te grupy wierszy spełniają jakiś warunek. Wiemy już, że po zastosowaniu klauzuli WHERE wyniki zapytania najpierw są filtrowane, a potem grupowane. Klauzula HAVING, tak jak WHERE, umożliwia określenie testu logicznego, ale w jej przypadku będzie on zastosowany do grup, a nie pojedynczych wierszy. Testy logiczne zawarte w klauzuli HAVING wykonywane są na całych grupach, a nie na pojedynczych rekordach. Tak więc klauzula ta służy do wybierania interesujących nas grup, a klauzula WHERE — interesujących nas wierszy. Warunek umieszczony w klauzuli HAVING wyrażony jest za pomocą dowolnej funkcji grupowej (listing 6.21).

Listing 6.21. Informacje o zamówieniach, których wartość przekroczyła 30. Iloczyn quantity*sell_price jest wyliczany dla każdego sprzedanego towaru, a następnie wyliczana jest suma wartości dla każdej grupy, czyli w tym przypadku dla każdego zamówienia. Na końcu klauzula HAVING usuwa z wyniku te grupy (zamówienia), których wartość nie przekroczyła 30.

SELECT orderinfo_id, SUM(quantity*sell_price)
FROM orderinfo JOIN orderline USING (orderinfo_id)
JOIN item USING (item_id)
GROUP BY orderinfo_id
HAVING  SUM(quantity*sell_price)> 30;
+--+--+
| orderinfo_id | SUM(quantity*sell_price) |
+--+--+
| 2            | 69.83                    |
| 3            | 33.44                    |
+--+--+ 


Klauzule HAVING i WHERE mogą wystąpić w tym samym zapytaniu — w takim przypadku najpierw będzie zastosowany test z klauzuli WHERE, a następnie — z klauzuli HAVING (listing 6.22).

Listing 6.22. Wyniki poprzedniego zamówienia ograniczone do zamówień złożonych w pierwszej połowie 2000 roku.



SELECT orderinfo_id, SUM(quantity*sell_price)
FROM orderinfo JOIN orderline USING (orderinfo_id)
JOIN item USING (item_id)
  WHERE date_placed BETWEEN '2000-01-01' AND '2000-06-31'
  GROUP BY orderinfo_id
  HAVING SUM(quantity*sell_price)> 30;
+--+--+
| orderinfo_id | SUM(quantity*sell_price) |
+--+--+
| 2            | 69.83                    |
+--+--+ 


Zapisanie w klauzuli HAVING warunku, który jest sprawdzany na poziomie wierszy nie jest błędem składniowym (czyli MySQL prawidłowo zinterpretuje i wykona takie zapytanie), ale taka instrukcja jest nie tylko nieelegancka i nieczytelna, ale również może być dłużej wykonywana (listing 6.23).

Listing 6.23. Klauzula HAVING użyta do wybierania wierszy

SELECT item_id, SUM(quantity*sell_price)
FROM orderinfo JOIN orderline USING (orderinfo_id)
JOIN item USING (item_id)
GROUP BY item_id
HAVING item_id IN (1,2,3,4);
++--+
| item_id | SUM(quantity*sell_price) |
++--+
| 1       | 65.85                    |
| 2       | 11.49                    |
| 3       | 2.49                     |
| 4       | 11.97                    |
++--+ 


W takim przypadku należy użyć klauzuli WHERE (listing 6.24).

Listing 6.24. Funkcjonalnie takie samo, ale czytelniejsze i szybsze rozwiązanie

SELECT item_id, SUM(quantity*sell_price)
FROM orderinfo JOIN orderline USING (orderinfo_id)
JOIN item USING (item_id)
WHERE item_id IN (1,2,3,4)
GROUP BY item_id;
++--+
| item_id | SUM(quantity*sell_price) |
++--+
| 1       | 65.85                    |
| 2       | 11.49                    |
| 3       | 2.49                     |
| 4       | 11.97                    |
++--+

 

© 2009 Wszystkie prawa zastrzeżone.

Załóż własną stronę internetową za darmoWebnode