No
GROUP BY
e ORDER BY
cláusula você pode fazer referência a aliases de coluna (colunas de saída) ou até mesmo números ordinais de SELECT
lista de itens. Cito o manual em ORDER BY
:
Cada expressão pode ser o nome ou número ordinal de uma coluna de saída (SELECT item de lista) , ou pode ser uma expressão arbitrária formada a partir de valores da coluna de entrada.
Minha ênfase em negrito.
Mas no
WHERE
e HAVING
cláusulas, você só pode se referir a colunas das tabelas base (colunas de entrada), então você tem que soletrar sua chamada de função. SELECT *, earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon)) AS dist
FROM venues
WHERE earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon)) <= radius
ORDER BY distance;
Se você quiser saber se é mais rápido empacotar o cálculo em um CTE ou subconsulta, basta testá-lo com
EXPLAIN ANALYZE
. (Eu duvido.) SELECT *
FROM (
SELECT *
,earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon)) AS dist
FROM venues
) x
WHERE distance <= radius
ORDER BY distance;
Como @Mike comentou, declarando uma função
STABLE
(ou IMMUTABLE
), você informa ao planejador de consultas que os resultados de uma chamada de função podem ser reutilizados várias vezes para chamadas idênticas em uma única instrução. Cito o manual aqui:
Uma função STABLE não pode modificar o banco de dados e tem a garantia de retornar os mesmos resultados com os mesmos argumentos para todas as linhas em uma única instrução. Esta categoria permite que o otimizador otimize várias chamadas da função para uma única chamada .
Minha ênfase em negrito.