2013-04-22 20 views
18

Jaka jest różnica między tymi 2 zapytaniami?MySql - HAVING vs WHERE

SELECT f.name, 
     u.name, 
     u.id 
FROM families f 
     JOIN units u 
     ON f.unit_id = u.id 
HAVING u.id IN(43, 413, 22) 

I:

SELECT f.name, 
     u.name, 
     u.id 
FROM families f 
     JOIN units u 
     ON f.unit_id = u.id 
WHERE u.id IN(43, 413, 22) 

Efektem tych 2 zapytań jest dokładnie taka sama. Gdzie jest różnica?

+0

Jeszcze wcześniej, lepiej duplikat można znaleźć na http://stackoverflow.com/questions/2905292/where-vs-having – thomasrutter

Odpowiedz

22

Różnica między klauzulami mającymi i where w sql jest taka, że ​​klauzula where nie może być używana z agregatami, ale klauzula ma. Jednym ze sposobów myślenia jest to, że klauzula mająca uprawnienia jest dodatkowym filtrem do klauzuli where.

Co jest lepsze: click

+2

Świetny artykuł i wyjaśnienie. Dzięki. –

+0

Ten artykuł jest niesamowicie pomocny, +1 – ocean800

+1

Czy ten link działa? Próbuję uzyskać dostęp, ale podano nieprawidłowy adres. Sprawdź, czy to tylko błąd. – vvtx

8

W tych pytaniach nic. Ale gdybyś użył GROUP BY zobaczysz różnicę. Jeśli użyjesz GROUP BY, zostanie zastosowana grupa HAVING, a przed zgrupowaniem danych zostanie zastosowana WHERE dla SELECT.

+3

Czy możesz podać przykład, w którym będę widzisz różnicę w tym zapytaniu? –

+0

Mogę. 'SELECT shapeType, count (shapeType) countShapeType z grup kształtów według shapeType HAVING countShapeType> 10' W tym zapytaniu wybierasz wszystkie kształty pogrupowane według typów kształtów i wyświetlasz tylko te typy, których masz więcej niż 10. Nie chciałbyś możesz to zrobić w instrukcji where, ponieważ nie masz dostępu do agregatu count. –

31

WHERE służy do wybierania danych w przetwarzanych oryginalnych tabelach.

HAVING służy do filtrowania danych w zestawie wyników utworzonym przez zapytanie. Oznacza to, że może odwoływać się do wartości zagregowanych i aliasów w klauzuli SELECT.

Na przykład, można napisać:

SELECT t1.val - t2.val diff 
FROM t1 JOIN t2 ON (some expression) 
HAVING diff > 10 

To nie będzie działać przy użyciu WHERE ponieważ diff jest aliasem, a nie jeden z pierwszych kolumn tabeli. Można napisać zamiast:

SELECT t1.val - t2.val diff 
FROM t1 JOIN t2 ON (some expression) 
WHERE t1.val - t2.val > 10 

ale to może trzeba zrobić wszystko, odejmowanie dwukrotnie: raz za wybór i ponownie produkować zestaw wyników.

+0

Jednak 'mając' może być również używany w zwykłych predagatach nieagregatowych, które działają z' where'. Na przykład. 'gdzie 1 = 1' a' mając 1 = 1'. Dlaczego jest to dozwolone? – Pacerier

+0

'HAVING' po prostu oblicza wyrażenie dla każdego wiersza w zestawie wyników. Jeśli jest to prawda, zachowuje wiersz w wynikach, w przeciwnym razie usuwa go. Dowolne wyrażenie jest dozwolone, jedyną różnicą jest to, że znajduje się w zakresie, w którym dostępne są również aliasy. – Barmar

+0

Mam na myśli, czy nie ma sensu umieszczać porównań nieagresywnych w 'mającym'? Czy nie powinno się ich umieścić w "miejscu"? – Pacerier