在内连接中SELECT AS colName,colName不存在(Postgres)

时间:2015-02-05 01:11:17

标签: postgresql

我在一个函数中有一个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也没有帮助。 我究竟做错了什么?谢谢!

1 个答案:

答案 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中的别名列将无法在HAVINGWHERE子句中起作用一张单数表,或者。

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)