分组MySQL列数据

时间:2011-11-10 20:15:44

标签: mysql group-by

首次发布,我会尽力遵守最佳做法。

我正在尝试构建一个测量用户位置的MySQL查询(在查询中分别表示为$Lat$Lng表示纬度和经度)。查询应该返回最接近用户的50个站点。

问题是我的表格中的数据包含每个站点入口的位置,我只需要每个站点最近的站点入口!

这是我的问题:

SELECT id, lat, lng, station_name, routes,
  ( 3959 * acos( cos( radians($Lat) )
  * cos( radians( lat ) ) * cos( radians( lng ) -
  radians($Lng) ) + sin( radians($Lat) ) * sin( radians( lat ) ) ) )  AS distance
FROM subway_stations ORDER BY distance LIMIT 0 , 50;

以上MySQL查询完成以下操作:

  1. 从id,lat,lng,station_name和路线
  2. 中选择数据
  3. 测量每个电台的lat和lng与用户的电台 - 将该数据存储为“距离”
  4. 返回最近的50个结果
  5. 我需要将这些结果组合在一起,以便每个站点只返回一个记录,距离列中值最小的记录,即最靠近用户的站点入口。

    我尝试过使用GROUP BY,但我似乎错误地实现了它,因为返回的结果不是理想的结果。

3 个答案:

答案 0 :(得分:0)

如果每个电台只需要一个最小的记录,则不需要LIMIT .. 只是做

$result = mysql_query("SELECT id, lat, lng, station_name, routes, MIN(
    ( 3959 * acos( cos( radians($Lat) ) * cos( radians( lat ) ) * 
    cos( radians( lng ) - radians($Lng) ) + sin( radians($Lat) ) * 
    sin( radians( lat ) ) ) ) AS distance )
FROM subway_stations 
GROUP BY station_name;

每个站点只返回一条距离最小的记录。

答案 1 :(得分:0)

如果不设置示例数据库,很难知道,但我怀疑您要进行以下更改:

  1. 在查询末尾添加group by station_name, id, lat, lng

  2. 不属于select子句的所有group by字段都需要聚合函数。最明显的是,distance应该需要min(...)

  3. 我不确定是否可以使用orderlimit子句。如果您遇到问题,请暂时(暂时)将它们拿出来并开始工作。为方便起见,请将此查询称为Q1。

  4. 如果无法使用order bylimit子句(实验并查看),则需要嵌套查询。这看起来像select * from (...Q1...) t1 ORDER BY distance LIMIT 0,50t1为内部选择分配了一个临时名称,但未在此查询中实际使用,但语法需要。

  5. 作为优化,您可能希望在内部having查询中添加Q1子句。也就是说,如果您知道边界距离,请添加HAVING distance<XXXXX

  6. 请注意,可能不需要步骤3 - 5,我不确定第3步。

答案 2 :(得分:0)

您可以更轻松地使用php获取每个站点最近的入口。

这实际上是一个常见问题,您需要使用子查询来解决。 我假设id只是一个行ID,并不是每个站唯一的。

SELECT subway_stations.* FROM (
    SELECT station_name, MIN(
        ( 3959 * acos( cos( radians($Lat) ) * cos( radians( lat ) ) * 
        cos( radians( lng ) - radians($Lng) ) + sin( radians($Lat) ) * 
        sin( radians( lat ) ) ) )
    ) AS distance 
    FROM subway_stations 
    GROUP BY station_name
) AS min_distances
JOIN subway_stations ON (
    min_distances.station_name = subway_stations.station_name
    AND ( 3959 * acos( cos( radians($Lat) ) * cos( radians( lat ) ) * 
        cos( radians( lng ) - radians($Lng) ) + sin( radians($Lat) ) * 
        sin( radians( lat ) ) ) 
    ) = min_distances.distance
)

这是解决您问题的典型“纯mysql”解决方案。但是,由于获取距离所涉及的计算程度,您可能希望:   - 使用您的初始查询,并使用php OR获取每个站的最短距离   - 运行上面的内部查询,但将其结果插入临时表,然后执行上述查询的等效操作,除非计算的距离替换为临时表的计算距离。