从MySQL 5.5转换为PostgreSQL 9.4时,我对此查询有疑问:
SELECT *, GCDist(?, ?, lat, lon) AS dist
FROM ads
HAVING dist < radius
ORDER BY date_created DESC
LIMIT ?;
其中GCDist
计算两点之间的大圆距离。
如果没有HAVING
子句,查询在Postgres上运行正常,但如果我想用dist > radius
过滤掉行,则会收到此错误:
错误:列&#34; dist&#34;不存在 第1行:... *,GCDist(0,0,lat,lon)AS dist from ads HAVING dist&lt; 100 ...
是否可以在PostgresSQL 9.4中使用查询的HAVING
子句中的函数输出?如果是这样,怎么样?
提前感谢您的任何提示。
以下是如何重现错误:
CREATE FUNCTION GCDist (
_lat1 FLOAT, -- Scaled Degrees north for one point
_lon1 FLOAT, -- Scaled Degrees west for one point
_lat2 FLOAT, -- other point
_lon2 FLOAT
) RETURNS FLOAT
IMMUTABLE AS
$$
-- Hardcoded constant:
DECLARE
_deg2km FLOAT DEFAULT 0.0111325;
_deg2rad FLOAT DEFAULT PI()/1800000; -- For scaled by 1e4 to MEDIUMINT
_rlat1 FLOAT DEFAULT _deg2rad * _lat1;
_rlat2 FLOAT DEFAULT _deg2rad * _lat2;
-- compute as if earth's radius = 1.0
_rlond FLOAT DEFAULT _deg2rad * (_lon1 - _lon2);
_m FLOAT DEFAULT COS(_rlat2);
_x FLOAT DEFAULT COS(_rlat1) - _m * COS(_rlond);
_y FLOAT DEFAULT _m * SIN(_rlond);
_z FLOAT DEFAULT SIN(_rlat1) - SIN(_rlat2);
_n FLOAT DEFAULT SQRT(_x * _x + _y * _y + _z * _z);
BEGIN
RETURN _deg2km * 2 * ASIN(_n / 2) / _deg2rad; -- again--scaled degrees
END;
$$
LANGUAGE plpgsql;
CREATE TABLE test (id SERIAL PRIMARY KEY, lat INTEGER NOT NULL, lon INTEGER NOT NULL);
INSERT INTO test (id, lat, lon) VALUES (DEFAULT, 10000, 10000);
INSERT INTO test (id, lat, lon) VALUES (DEFAULT, 20000, 20000);
INSERT INTO test (id, lat, lon) VALUES (DEFAULT, 50000, 50000);
SELECT *, GCDist(0, 0, lat, lon) AS dist FROM test HAVING dist < 200;
MySQL上的输出表类似于以下内容:
id | lat | lon | dist
---+-----+-----+------
1 |10000|10000|157.43
答案 0 :(得分:3)
由于您没有使用group by
,因此首先没有用(和错误),在这种情况下您应该使用where
子句。
要访问where
子句中的列别名,您需要将查询包装在派生表中:
select *
from (
SELECT *,
GCDist(0, 0, lat, lon) AS dist
FROM test
) t
where dist < 200;
或者只是重复一下表达式
SELECT *, GCDist(0, 0, lat, lon) AS dist
FROM test
WHERE GCDist(0, 0, lat, lon) < 200;
另见:
答案 1 :(得分:1)
是否可以在PostgresSQL 9.4中使用查询的HAVING子句中的函数输出?如果是这样,怎么样?
是,与WHERE子句相同。请参阅a-horse-no-name所示的两个解决方案中的第二个。