GDZIE vs POSIADANIE

247

Dlaczego musisz umieszczać kolumny, które sam tworzysz (na przykład select 1 as "number") po MySQL, HAVINGa nie WHEREw MySQL?

I czy są jakieś wady zamiast robić WHERE 1(zapisywanie całej definicji zamiast nazwy kolumny)?

baloo
źródło

Odpowiedzi:

323

Dlaczego musisz umieścić kolumny, które sam tworzysz (na przykład „wybierz 1 jako liczbę”) po HAVINGU, a nie GDZIE w MySQL?

WHEREjest stosowany przed GROUP BY, HAVINGjest stosowany po (i może filtrować według agregatów).

Ogólnie rzecz biorąc, można odwoływać aliasy w żadnym z tych klauzul, ale MySQLpozwala na przedstawieniu SELECTaliasy w poziomie GROUP BY, ORDER BYa HAVING.

I czy są jakieś wady zamiast robić „GDZIE 1” (zapisywanie całej definicji zamiast nazwy kolumny)

Jeśli obliczone wyrażenie nie zawiera żadnych agregatów, umieszczenie go w WHEREklauzuli najprawdopodobniej będzie bardziej wydajne.

Quassnoi
źródło
289

Wszystkie inne odpowiedzi na to pytanie nie trafiły w kluczowy punkt.

Załóżmy, że mamy tabelę:

CREATE TABLE `table` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `value` int(10) unsigned NOT NULL,
 PRIMARY KEY (`id`),
 KEY `value` (`value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

I mają 10 wierszy o identyfikatorze i wartości od 1 do 10:

INSERT INTO `table`(`id`, `value`) VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5),(6, 6),(7, 7),(8, 8),(9, 9),(10, 10);

Wypróbuj następujące 2 zapytania:

SELECT `value` v FROM `table` WHERE `value`>5; -- Get 5 rows
SELECT `value` v FROM `table` HAVING `value`>5; -- Get 5 rows

Otrzymasz dokładnie takie same wyniki, możesz zobaczyć, że klauzula HAVING może działać bez klauzuli GROUP BY.


Oto różnica:

SELECT `value` v FROM `table` WHERE `v`>5;

Błąd # 1054 - Nieznana kolumna „v” w „klauzula”

SELECT `value` v FROM `table` HAVING `v`>5; -- Get 5 rows

Klauzula WHERE zezwala warunkowi na użycie dowolnej kolumny tabeli, ale nie może używać aliasów ani funkcji agregujących. Klauzula HAVING pozwala warunkowi na użycie wybranej (!) Kolumny, aliasu lub funkcji agregującej.

Jest tak, ponieważ klauzula WHERE filtruje dane przed wyborem, ale klauzula HAVING filtruje dane wynikowe po wybraniu.

Więc wstaw warunki do klauzuli WHERE będą bardziej wydajne, jeśli masz wiele wielu wierszy w tabeli.

Spróbuj WYJAŚNIĆ, aby zobaczyć kluczową różnicę:

EXPLAIN SELECT `value` v FROM `table` WHERE `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
|  1 | SIMPLE      | table | range | value         | value | 4       | NULL |    5 | Using where; Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+

EXPLAIN SELECT `value` v FROM `table` having `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
|  1 | SIMPLE      | table | index | NULL          | value | 4       | NULL |   10 | Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

Możesz zobaczyć GDZIE lub POZYCJA używa indeksu, ale wiersze są różne.

Ryba płonąca
źródło
32
Doceniam to, że wspomniałeś WYJAŚNIJ!
paiego,
Ponieważ klauzula HAVING filtruje dane po wybraniu, klauzula WHERE będzie bardziej skuteczna. Więc jeśli to prawda, to kiedy musimy korzystać z HAVING zamiast GDZIE?
grep
5
@grep W przypadku konieczności filtrowania danych po wybraniu, potrzebujesz klauzuli HAVING, zwykle używamy jej z klauzulą ​​GROUP BY, np .: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrowned
1
Doskonały post. Kilka proponowanych wyjaśnień: Zmień ...HAVING clause can use both column and alias.się ...HAVING clause can use either column or alias.i zmiany ...WHERE clause will be more effectivedo...WHERE clause will be more efficient
rmirabelle
2
Klauzula HAVING została dodana do SQL, ponieważ słowa kluczowego WHERE nie można było używać z funkcjami agregującymi.
Shashank Vivek,
62

Główną różnicą jest to, że WHEREnie można jej użyć na zgrupowanym elemencie (np. SUM(number)), Podczas gdy HAVINGmożna.

Powodem jest WHEREto zrobić przed zgrupowania i HAVINGodbywa się po ugrupowanie jest gotowe.

David Brunelle
źródło
39

HAVINGsłuży do filtrowania agregacji w twoim GROUP BY.

Na przykład, aby sprawdzić zduplikowane nazwy:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
Kevin McKelvin
źródło
1
Jest to prawdą w niektórych zachowanych. Nadal możesz umieścić całe „Where” w klauzuli „have”.
David Brunelle
8

Te 2 będą wyglądały tak samo jak pierwsze, ponieważ oba są używane do powiedzenia o warunku do filtrowania danych. Chociaż w każdym razie możemy użyć słowa „mieć” zamiast „gdzie”, istnieją jednak przypadki, w których nie możemy użyć słowa „gdzie” zamiast „mieć”. Jest tak, ponieważ w zapytaniu select „gdzie” filtruje dane przed „select”, a „mając” filtruje dane po „select”. Tak więc, gdy używamy aliasów, które nie znajdują się w bazie danych, „gdzie” nie może ich zidentyfikować, ale „posiadanie” może.

Np .: niech tabela Uczeń zawiera identyfikator studenta, imię, datę urodzin, adres. Przyjmij, że data urodzin to data.

SELECT * FROM Student WHERE YEAR(birthday)>1993; /*this will work as birthday is in database.if we use having in place of where too this will work*/

SELECT student_id,(YEAR(CurDate())-YEAR(birthday)) AS Age FROM Student HAVING Age>20; 
/*this will not work if we use ‘where’ here, ‘where’ don’t know about age as age is defined in select part.*/
Nuwantha
źródło
1
Ten przykład z prawdziwego życia w pełni wyjaśnia różnicę między WHEREi HAVING.
WM
Wyraźnie pokazuje różnicę między posiadaniem a miejscem. Dzięki.
MarcoZen
3

GDZIE filtruje przed zgrupowaniem danych, a HAVING filtruje po zgrupowaniu danych. To ważne rozróżnienie; wiersze, które są eliminowane przez klauzulę WHERE , nie zostaną uwzględnione w grupie. Może to zmienić obliczone wartości, co z kolei (= w rezultacie) może wpłynąć na to, które grupy są filtrowane na podstawie użycia tych wartości w klauzuli HAVING .

I kontynuuje

HAVING jest tak podobny do GDZIE, że większość DBMS traktuje je tak samo, jeśli nie określono GROUP BY . Niemniej jednak powinieneś sam to rozróżnić. Używaj opcji HAVING tylko w połączeniu z klauzulami GROUP BY . Użyj GDZIE do standardowego filtrowania na poziomie wiersza.

Fragment: Forta, Ben. „Sams Naucz się SQL w 10 minut (wydanie 5) (Sams Naucz się ...).”.

snr
źródło
1

Posiadanie jest używane tylko z agregacją, ale gdzie z instrukcjami bez agregacji Jeśli masz słowo, które umieść przed agregacją (pogrupuj według)

Hos Mercury
źródło