我目前正在尝试使用Haversine公式为我的商业目录网站制作定位器。我的查询当前返回where子句中的错误未知列距离。我不知道为什么。这应该有效,因为我已经在Haversine公式之后直接定义了距离别名。有什么想法吗?
SELECT
l.listing_id AS id, l.category_id, l.title AS listing_title, l.description, l.address, l.city, l.zip, UNIX_TIMESTAMP(l.date_submitted) AS date_submitted, l.latitude, l.longitude,
( 6371 * acos( cos( radians(40.293861) ) * cos( radians( l.latitude ) ) * cos( radians( l.longitude ) - radians(-76.600252) ) + sin( radians(40.293861) ) * sin( radians( l.longitude ) ) ) ) AS distance,
c.category_id AS cat_id, c.title AS cat_title, c.slug AS cat_slug,
r.region_id AS region_id, r.title AS region_title, r.slug AS region_slug
FROM listings AS l
LEFT JOIN categories AS c ON l.category_id = c.category_id
LEFT JOIN regions AS r ON l.region_id = r.region_id
WHERE distance < 10
ORDER BY l.date_submitted DESC
答案 0 :(得分:1)
如上所述,您不能在WHERE子句中使用别名,因为该值仍然未知。
我想指出的是,当你显示它时,这个查询不会扩展,因为你有越来越多的行,因为MySQL无法缩小可能匹配的数量。< / p>
一个好的方法是添加一个WHERE条件,用于定义一个内部有圆形区域的方形区域。通过这种方式,您的SQL将不会扫描整个世界,但会过滤那些区域与圆形区域“足够接近”的行;然后计算低于10的距离。
例如,如果你正在寻找X点Y的距离10;你可以说
WHERE
latitude < (X+5) AND latitude > (X-5) AND longitude < (Y+5) AND longitude > (Y-5)
这意味着你忽略了一组行,然后对一部分行进行了昂贵的计算;这比在整个数据集上进行昂贵的计算要快得多。
我希望这可以帮助您获得更快,更具伸缩性的应用程序。
答案 1 :(得分:0)
您根本无法在WHERE子句中使用ALIAS。
MySQL Manual, B.5.4.4 Problems with Column Aliases:
“标准SQL不允许在WHERE子句中引用列别名。强制执行此限制是因为在评估WHERE子句时,可能尚未确定列值。“
您必须重复计算WHERE子句中的值的公式。
答案 2 :(得分:0)
最常见的解决方法是将查询视为派生表,然后在外部查询中使用列别名,例如
SELECT
d.*
FROM (
SELECT
l.listing_id AS id
, l.category_id
, l.title AS listing_title
, l.description
, l.address
, l.city
, l.zip
, UNIX_TIMESTAMP(l.date_submitted) AS date_submitted
, l.latitude
, l.longitude
, (6371 * ACOS(COS(RADIANS(40.293861)) * COS(RADIANS(l.latitude)) * COS(RADIANS(l.longitude) - RADIANS(-76.600252)) + SIN(RADIANS(40.293861)) * SIN(RADIANS(l.longitude)))) AS distance
, c.category_id AS cat_id
, c.title AS cat_title
, c.slug AS cat_slug
, r.region_id AS region_id
, r.title AS region_title
, r.slug AS region_slug
FROM listings AS l
LEFT JOIN categories AS c ON l.category_id = c.category_id
LEFT JOIN regions AS r ON l.region_id = r.region_id
) d
WHERE d.distance < 10
ORDER BY
d.date_submitted DESC
HAVING子句不能替代where子句,HAVING子句允许按聚合值进行过滤(例如,SUM(sales)&gt; 1000)
答案 3 :(得分:0)
正如其他答案中已经指出的那样,我可以想到3种通用方法。我试着用这个小提琴
http://sqlfiddle.com/#!9/c8e411/6
使用子查询来派生列并在外部查询中使用where
。
在用于派生列
在所有列上使用group by并使用having子句。如果查询已经使用了group by那么你必须相应地调整它。