【问题标题】:How to reuse variable from SQL SELECT statement in WHERE clause如何在 WHERE 子句中重用 SQL SELECT 语句中的变量
【发布时间】:2020-08-04 12:21:32
【问题描述】:

我需要根据与任何给定点的距离从数据库中取出值,然后按距离升序排序。经度和纬度作为浮点字段保存在数据库中。这是我的查询

SELECT
   *,
   @distance : = 6371 * 2 * asin(sqrt(POW(sin(({lat} - radians(address.latitude)) / 2), 2) + cos({lat}) * cos(radians(address.latitude)) * POW(sin(({lon} - radians(address.longitude)) / 2), 2))) 
FROM
   service,
   provider,
   address 
WHERE
   service.provider_id = provider.id 
   AND provider.address_id = address.id 
   AND provider.status = True 
   AND 
   (
      6371 * 2 * asin(sqrt(POW(sin(({lat} - radians(address.latitude)) / 2), 2) + cos({lat}) * cos(radians(address.latitude)) * POW(sin(({lon} - radians(address.longitude)) / 2), 2)))
   )
   < 10 
order by
   @distance

我需要为 where @distance 等条件重用 distance 但我无法重用,它返回空列表。而 ORDER BY 中的 @distance 工作正常。如何在 where 子句中重用变量?

【问题讨论】:

  • '如何在 where 子句中重用变量?'您不能按操作顺序在 select 之前执行 where ,因此该变量不存在。请研究sql操作顺序。

标签: mysql database django-models


【解决方案1】:

假设您在选择之外不需要@DISTANCE,这是一种尝试的方法:

    SELECT *,
            6371 * 2 * asin(sqrt(POW(sin(({lat} - radians(address.latitude)) / 2), 2) + cos({lat}) * cos(radians(address.latitude)) * POW(sin(({lon} - radians(address.longitude)) / 2), 2))) AS DISTANCE
    FROM    service,
            provider,
            address 
    WHERE
        service.provider_id = provider.id 
        AND provider.address_id = address.id 
        AND provider.status = True 
    HAVING 
        DISTANCE < 10 
    ORDER BY
        DISTANCE

请注意,我为计算提供了一个别名 DISTANCE(参见选择的最右侧),并使用 HAVING 而不是 WHERE 作为对别名的引用。

【讨论】:

  • @TheImpaler 的 cmets 和使用 JOIN 的查询是绝对正确的 - 我没有解决这个问题,因为它与您的问题无关。
  • 这是返回原始查询集,因此我无法应用之后需要的 querySet 方法,这使得代码变得复杂和混乱,有没有办法用查询集来做到这一点?这样我就可以在这个结果上应用 .filter 之类的方法?
  • 对不起,我对 django-models 不熟悉。
【解决方案2】:

避免使用 MySQL 变量;它们在较新版本的 MySQL 中已过时。此外,最好使用现代语法连接 (SQL-92) 而不是旧连接。

无论如何,我认为以下查询会产生您想要的结果:

select *
from (
  SELECT
    *,
    6371 * 2 * asin(sqrt(POW(sin(({lat} - radians(a.latitude)) / 2), 2) 
      + cos({lat}) * cos(radians(a.latitude)) * POW(sin(({lon} 
      - radians(a.longitude)) / 2), 2))) as distance
  FROM service s
  JOIN provider p ON s.provider_id = p.id
  JOIN address a ON p.address_id = a.id
  WHERE p.status = True 
) x
WHERE distance < 10
ORDER BY distance

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    • 2013-10-10
    • 2014-02-16
    • 2013-07-07
    • 1970-01-01
    • 2011-09-19
    相关资源
    最近更新 更多