Czy możesz użyć aliasu w klauzuli WHERE w mysql?

121

Muszę użyć aliasu w klauzuli WHERE, ale ciągle mówi mi, że jest to nieznana kolumna. Czy jest jakiś sposób na obejście tego problemu? Muszę wybrać rekordy, które mają ocenę wyższą niż x. Ocena jest obliczana jako następujący alias:

sum(reviews.rev_rating)/count(reviews.rev_id) as avg_rating
dreftymac
źródło

Odpowiedzi:

229

Możesz użyć klauzuli HAVING, która może zobaczyć aliasy, np

 HAVING avg_rating>5

ale w klauzuli where będziesz musiał powtórzyć swoje wyrażenie, np

 WHERE (sum(reviews.rev_rating)/count(reviews.rev_id))>5

ALE! Nie wszystkie wyrażenia będą dozwolone - użycie funkcji agregującej, takiej jak SUMA, nie będzie działać, w takim przypadku będziesz musiał użyć klauzuli HAVING.

Z podręcznika MySQL :

Nie jest dozwolone odwoływanie się do aliasu kolumny w klauzuli WHERE, ponieważ wartość kolumny może nie zostać jeszcze określona podczas wykonywania klauzuli WHERE. Zobacz Sekcja B.1.5.4, „Problemy z aliasami kolumn” .

Paul Dixon
źródło
1
Jeśli powtórzę wyrażenie, powie mi: „nieprawidłowe użycie funkcji grupy”
3
Przeformułowałem, aby było jaśniej, funkcje agregujące są niedozwoloned
Paul Dixon
Niezłe wyjaśnienie, zwł. klauzula „but in a where… powtórz ..” część
th3an0maly
4
To dobra odpowiedź, ale proszę wziąć pod uwagę wpływ na wydajność, ponieważ jest HAVINGwykonywany po pobraniu danych i WHEREwykonywany wcześniej.
StockB
W klauzuli WHERE nie można używać funkcji agregujących. Klauzula WHERE filtruje tylko wiersze pojedynczo, a nie całe grupy.
Bill Karwin
33

Nie wiem, czy to działa w mysql, ale używając sqlserver możesz po prostu opakować to tak:

select * from (
  -- your original query
  select .. sum(reviews.rev_rating)/count(reviews.rev_id) as avg_rating 
  from ...) Foo
where Foo.avg_rating ...
Torbjörn Gyllebring
źródło
7

To pytanie jest dość stare, a jedna odpowiedź zdobyła już 160 głosów ...

Mimo to chciałbym wyjaśnić: pytanie w rzeczywistości nie dotyczy tego, czy aliasy mogą być używane w WHEREklauzuli.

sum(reviews.rev_rating) / count(reviews.rev_id) as avg_rating

jest agregacją. W WHEREklauzuli ograniczamy rekordy, które chcemy z tabel, patrząc na ich wartości. sum(reviews.rev_rating)a count(reviews.rev_id)jednak nie są wartościami, które znajdziemy w zapisach; są to wartości, które otrzymujemy dopiero po zagregowaniu rekordów.

Więc WHEREjest to niewłaściwe. Potrzebujemy HAVING, ponieważ chcemy ograniczyć wiersze wyników po agregacji. To niemożliwe

WHERE avg_rating > 10

ani

WHERE sum(reviews.rev_rating) / count(reviews.rev_id) > 10

W związku z tym.

HAVING sum(reviews.rev_rating) / count(reviews.rev_id) > 10

z drugiej strony jest możliwy i zgodny ze standardem SQL. Natomiast

HAVING avg_rating > 10

jest możliwe tylko w MySQL. Nie jest to poprawny kod SQL według standardu, ponieważ SELECTklauzula ma zostać wykonana po HAVING. Z dokumentacji MySQL:

Inne rozszerzenie MySQL w stosunku do standardowego SQL zezwala w klauzuli HAVING na aliasy wyrażeń na liście wyboru.

Rozszerzenie MySQL zezwala na użycie aliasu w klauzuli HAVING dla kolumny zagregowanej

https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

Thorsten Kettner
źródło
0

Jeśli zapytanie jest statyczne, możesz zdefiniować je jako widok, a następnie możesz użyć tego aliasu w klauzuli where podczas wykonywania zapytania dotyczącego widoku.

alpere
źródło
0
SELECT * FROM (SELECT customer_Id AS 'custId', gender, age FROM customer
    WHERE  gender = 'F') AS c
WHERE c.custId = 100;
anson
źródło