MySQL在针对Store Locator-Google Maps App的Group By查询中选择错误的列值
Posted
技术标签:
【中文标题】MySQL在针对Store Locator-Google Maps App的Group By查询中选择错误的列值【英文标题】:MySQL Selecting wrong column value in Group By query for Store Locator-Google Maps App 【发布时间】:2011-01-29 23:51:25 【问题描述】:首先我必须声明我是一个极端的新手。已经使用 php 和 mysql 大约 4 周了。如果我没有正确格式化这个问题或没有使用正确的艺术术语,请提前接受我的道歉。
我正在构建一个商店定位器应用程序。为了进行测试,我有一个名为“位置”的表,其中包含 5 家不同连锁餐厅的名称、地址和纬度/经度数据,总共有 1500 条(位置)记录。
我让该应用程序作为标准商店定位器运行良好,用户在其中输入他们的地址和以英里为单位的距离进行搜索。删除 GROUP BY 语句后,下面的代码会正确返回这些结果。例如,当用户输入他们的地址和距离进行搜索时,SELECT 语句会返回该距离内的所有餐厅。
我的应用要求只返回和显示用户指定距离内的每个连锁餐厅最近的位置。我添加了 GROUP BY 语句来完成此操作。返回正确数量的记录以及正确的 loc_name 和与用户的距离。但是,所有其他字段都不正确。它们似乎是从 MIN 值之外的其他记录中随机选择的。例如,返回的第一条记录是距离 4.38 英里的 DAIRY QUEEN - 正确。但是,DAIRY QUEEN 在 4.38 英里处的地址、州、城市等不正确。
我已广泛阅读有关 GROUP BY 的问题以及使用 INNER JOIN 的要求也许可以解决我的问题? *** 中最近的一个问题和答案非常具体地解决了这个问题,请参阅MySQL Selecting wrong column value in Group By query。到目前为止,我读过的所有解决方案都会让我使用计算出的距离作为执行 JOIN 的键,但我不知道这怎么可能。
问题 1:如何构造 SELECT 语句以获得我想要的结果:位置表中每个连锁餐厅只有一个的完整数据字段行?
关于我的代码不像看起来那么可怕并且不需要理解来解决我的问题的注释:
MIN() 中的三角公式计算用户地址(转换为纬度/经度)与每个位置记录的纬度/经度之间的距离(以英里为单位)。相信我,这行得通。
ORDER BY 13 语句:表示按 SELECT 中列出的第 13 个字段进行排序,在这种情况下,它是别名“距离”。我提到这一点是因为我注意到这种语法并不为人所知。
WHERE 语句后面的代码检查用户的地址(以纬度/经度为单位)是否在一个带有纬度/经度角的框内,这些角是用户指定的要搜索的位置距离。这称为“边界框”。它用于优化搜索时间。可以简单地测试一下“距离”是否小于用户输入的距离,但这需要读取整个位置文件。生产版本将包含大约一百万条记录。位置表有一个索引:(loc_lat,loc_lon,loc_id)。我的理解是在WHERE语句中使用Bounding Box会限制需要读取的索引的范围。问题 2:这是我实现的方式,是否会按照我描述的方式进行处理?问题1的解决方案会保留优化吗?
提前感谢大家的帮助。我真的才 4 周进入 mySQL 和 PHP,你可以看到,在我的头上?
我的问题归结为这一点。应该如何修改此 SELECT 以仅返回 1 个位置表记录,其中每个 loc_name 的对应字段是与用户输入地址的最小距离??
SELECT loc_id,loc_name,loc_address_1,loc_address_2,loc_city,
loc_state,loc_postal_code,loc_phone,loc_fax,
loc_lat,loc_lon,loc_geocoded_status,
MIN( ((ACOS( SIN( $lat * PI( ) /180 ) * SIN( loc_lat * PI( ) /180 ) +
COS( $lat * PI( ) /180 ) * COS( loc_lat * PI( ) /180 ) *
COS( ($long - loc_lon) * PI( ) /180 ) ) *180 / PI( )) *60 * 1.1515) )
AS distance
FROM locations WHERE (loc_lat between $lat1 and $lat2
AND loc_lon between $lon1 and $lon2)
AND loc_geocoded_status = 1
GROUP BY loc_name
ORDER BY 13
【问题讨论】:
【参考方案1】:您在四个星期内取得了长足的进步。它有助于包含最少的 DDL 和 INSERT 语句,以鼓励更多人响应。
我将 GROUP BY 语句添加到 做到这一点。正确的数量 记录返回正确的 loc_name 和与用户的距离。 但是,所有其他字段都是 永远不正确。他们似乎随机 从其他记录中选择 在 MIN 值之外。
是的,这对 MySQL 来说很正常。文章 MySQL Standard Group By 解释了这种行为。
一个不确定的结果集是 当一个或多个返回 SELECT 中的非聚合列 子句未在 GROUP BY 中列出 条款。列中列出的列 SELECT 子句但从 GROUP BY 子句返回无意义 值,因为它们是列值 从所有人中不确定地选择 预先聚合的行。
您需要一个确定的结果集,而不是不确定的结果集。此语句应为您提供一个两列结果集,每个位置名称包含一行。
SELECT loc_name, MIN( ((ACOS( . . . ) AS distance
FROM locations
GROUP BY loc_name
您应该能够使用该语句和位置名称和距离上的 JOIN 表达式来获取您需要的其他列。
我将算术封装在一个名为“距离”的函数中,然后
SELECT L1.*, C.*
FROM locations L1
INNER JOIN (SELECT L2.loc_name,
MIN(distance($lat, $lon,
L2.loc_lat, L2.loc_lon)) AS distance
FROM locations L2
GROUP BY L2.loc_name) C
ON L1.loc_name = C.loc_name
AND C.distance = distance($lat, $lon,
L1.loc_lat, L1.loc_lon)
您需要添加边界框信息。当我试图确保 JOIN 正常工作时,我把它遗漏了。我在内部 SELECT 子句中有一个不必要的 ORDER BY,但那是一个 pre-caffeine 子句,所以我删除了它。
您可能还需要 loc_name 的索引,因为它在 GROUP BY
中使用。请参阅 MySQL 的文档以获取 EXPLAIN syntax。
【讨论】:
以上是关于MySQL在针对Store Locator-Google Maps App的Group By查询中选择错误的列值的主要内容,如果未能解决你的问题,请参考以下文章
针对 App Store 中的 iPhone 6 信息文本进行了优化
iOS 应用程序可以针对 App Store 中的某些用户吗?
Apple ResearchKit 中的额外本地化是不是会导致 iOS App Store 错误地认为我们的应用已针对许多额外语言进行了本地化?