我在一个函数中有一个SELECT子句,我在这个函数中加入两个表,以便找到在用户一定距离内并且当前打开的餐馆。出于某种原因,当我运行此功能时,我得到以下内容 错误:
ERROR: column "distance" does not exist
LINE 10: distance < searchDist AND
^
这是我的代码:
CREATE OR REPLACE FUNCTION get_nearby_open_restaurants (searchDist integer, myLat numeric, myLon numeric)
RETURNS json AS $$
BEGIN
CREATE TEMPORARY TABLE nearbyOpenRestaurants AS
SELECT Restaurants.restaurantID, Restaurants.name, Restaurants.type,
Restaurants.address, Restaurants.deliveryDistance,
(3959 * acos(cos(radians(myLat)) * cos(radians(latitude)) *
cos(radians(longitude) - radians(myLon)) +
sin(radians(myLat)) * sin(radians(latitude)))) AS distance,
BusinessHours.hoursJSON
FROM Restaurants, BusinessHours
WHERE Restaurants.RestaurantID = BusinessHours.RestaurantID AND
distance < searchDist AND
distance < Restaurants.deliveryDistance
/*Check if the restaurant is open here*/
;
RETURN to_json(nearbyOpenRestaurants);
DROP TABLE nearbyOpenRestaurants;
END;
$$ LANGUAGE plpgsql;
为了澄清,包含距离计算的SELECT AS子句在其表中运行得很好,如下所示:
SELECT restaurantID, name, type, address, deliveryDistance,
(3959 * acos(cos(radians(myLat)) * cos(radians(latitude)) *
cos(radians(longitude) - radians(myLon)) +
sin(radians(myLat)) * sin(radians(latitude)))) AS distance
FROM Restaurants
HAVING distance < searchDist AND distance < deliveryDistance;
所以当我将两张桌子连在一起时,这个问题才存在。 HAVING子句似乎对加入的SELECT也没有帮助。 我究竟做错了什么?谢谢!
答案 0 :(得分:0)
您的问题是,distance
此处是SELECT
中的WHERE
子句中尚未提供的别名。在另一个表中,它只是另一列。
因此,代替distance
中的WHERE
,重复整个操作:
sin(radians(myLat)) * sin(radians(latitude))))
所以你的WHERE
条款会变成:
WHERE Restaurants.RestaurantID = BusinessHours.RestaurantID AND
( sin(radians(myLat)) * sin(radians(latitude)))) ) < searchDist AND
( sin(radians(myLat)) * sin(radians(latitude)))) ) < Restaurants.deliveryDistance
我添加了封闭的parens以进一步描绘并增加额外的清晰度。
根据OP的评论进行编辑:
如果要重新使用SELECT
中的WHERE
中的值,则重复计算就是 SQL 中需要完成的方式。相同的查询。一般来说,重做计算不是一个大问题(我相信它有一些缓存来帮助解决这个问题),我怀疑这些计算,这是简单的数学计算,也不例外,所以我建议你去做这个重复方法。
如果您碰巧遇到某些事情确实是一个昂贵的查询,并且您发现内置缓存确实使表达式变得昂贵,则有两种选择:
一种是使用CTE,其中涉及WITH
表达式。这适用于独立查询,即不依赖于您将使用它的查询的输入的查询。这基本上用作查询范围的临时表。但是,在您的情况下,重复的表达式不是常量 - 它会根据JOIN
ed表中的特定行而更改 - 因此 CTE 对您不起作用。< / p>
另一种方法是将SELECT
包裹在另一个SELECT
内,将WHERE
子句移到外部SELECT
,以便distance
列可用于你在外面的SELECT
。但是,使用这种方法,您需要确保内部SELECT
返回其SELECT
子句中所需的外部WHERE
所需的所有必需列,这需要在您的案例中添加列虽然如果使用较新的JOIN
语法,并且标准被移到WHERE
之外,那么整体看起来似乎比查询要复杂得多,尽管复杂性可能会有所降低。而是使用了JOIN ... ON
。
所以,再次,我建议重复表达式。如果绝对必要,只尝试进一步优化。
以回复方式编辑来自OP的第二条评论:
它与表是否已加入无关 - 引用SELECT
中的别名列将无法在HAVING
或WHERE
子句中起作用一张单数表,或者。
e.g。
mydb=# create table bar (id serial, val decimal);
CREATE TABLE
mydb=# insert into bar (val) values (1.2), (1.1), (3.2);
INSERT 0 3
mydb=# select * from bar;
id | val
----+-----
1 | 1.2
2 | 1.1
3 | 3.2
(3 rows)
mydb=# select id, val, sin(val) from bar;
id | val | sin
----+-----+---------------------
1 | 1.2 | 0.932039085967226
2 | 1.1 | 0.891207360061435
3 | 3.2 | -0.0583741434275801
(3 rows)
mydb=# select id, val, sin(val) as narf from bar;
id | val | narf
----+-----+---------------------
1 | 1.2 | 0.932039085967226
2 | 1.1 | 0.891207360061435
3 | 3.2 | -0.0583741434275801
(3 rows)
mydb=# select id, val, sin(val) as narf from bar having narf > 0;
ERROR: column "narf" does not exist
LINE 1: select id, val, sin(val) as narf from bar having narf > 0;
^
mydb=# select id, val, sin(val) as narf from bar having sin(val) > 0;
ERROR: column "bar.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: select id, val, sin(val) as narf from bar having sin(val) > ...
^
mydb=# select id, val, sin(val) as narf from bar where narf > 0;
ERROR: column "narf" does not exist
LINE 1: select id, val, sin(val) as narf from bar where narf > 0;
^
mydb=# select id, val, sin(val) as narf from bar where sin(val) > 0;
id | val | narf
----+-----+-------------------
1 | 1.2 | 0.932039085967226
2 | 1.1 | 0.891207360061435
(2 rows)