为什么 PostgreSQL 中不存在带有“have”子句的别名?

Lok*_*dey 0 postgresql postgresql-9.6 postgresql-performance column-alias

我正在尝试计算两个坐标之间的距离并根据一些条件获取一些信息。一个类似的带有 'have' 子句的查询在 MySQL 中工作。但是为什么它在 PostgreSQL 中不起作用呢?

这是我的查询:

    SELECT *, ( 6371 * acos( cos( radians(latitude) ) * cos( radians( latitude1 ) ) *
    cos( radians( longitude1 ) - radians(longitude) ) + sin( radians(latitude) ) *
    sin( radians( latitude1 ) ) ) ) AS distance from table WHERE
    verified=true AND best_for LIKE '%xyz%' AND uuid NOT IN (SELECT uuid::uuid FROM table2 WHERE
    from_date BETWEEN '2020-12-17 06:30'::date AND '2020-12-18 12:30'::date AND
    to_date BETWEEN '2020-12-17 06:30'::date AND '2020-12-18 12:30'::date  AND )
    HAVING distance < 50 ORDER BY distance
Run Code Online (Sandbox Code Playgroud)

为什么距离不存在?以及如何修改此查询以使其在 PostgreSQL 中工作?

a_h*_*ame 6

这是 SQL 标准设置的规则(MySQL 忽略标准定义的一些规则并允许无效 SQL)。

您不能在定义它的同一级别上使用列别名,并且having只能在使用聚合的查询中使用。如果要避免重复表达式,请使用派生表。

它通常也更快,NOT EXISTS而不是使用NOT IN

SELECT *
FROM (
  SELECT *, 
        ( 6371 * acos( cos( radians(latitude) ) * cos( radians( latitude1 ) ) * 
          cos( radians( longitude1 ) - radians(longitude) ) + sin( radians(latitude) ) * 
          sin( radians( latitude1 ) ) ) ) AS distance 
  from table t1
  WHERE verified = true 
    AND best_for LIKE '%xyz%' 
    AND NOT EXISTS (SELECT *
                     FROM table2 t2
                     WHERE t2.from_date BETWEEN '2020-12-17 06:30'::date AND '2020-12-18 12:30'::date 
                       AND t2.to_date BETWEEN '2020-12-17 06:30'::date AND '2020-12-18 12:30'::date  
                       AND t2.uuid::uuid = t1.uuid)
) x                       
WHERE distance < 50 
ORDER BY distance
Run Code Online (Sandbox Code Playgroud)