Select 大集合中看起来均匀分布在该区域中的几个坐标

Select a few coordinates from a large set that look evenly distributed in the area

我有一个 MySQL table 区域和 lat/lon 位置列。每个区域都有很多位置,比如 20.000。有没有办法只挑选几个,比如 100,在地图上看起来分布均匀?

分布不一定要完美,查询速度更重要。如果直接使用 MySQL 无法做到这一点,那么以某种方式选择均匀分布的位置的非常快速的算法也可能有效。

提前致谢。

编辑:回答评论中的一些请求。数据没有什么可以用的,只是面积和位置坐标,例如:

+-------+--------------+----------+-----------+------------+--------+--------+
| id    | area         | postcode | lat       | lon        | colour | size   |
+-------+--------------+----------+-----------+------------+--------+--------+
| 16895 | Athens       |    10431 | 37.983917 | 23.7293599 | red    | big    |
| 16995 | Athens       |    11523 | 37.883917 | 23.8293599 | green  | medium |
| 16996 | Athens       |    10432 | 37.783917 | 23.7293599 | yellow | small  |
| 17000 | Thessaloniki |    54453 | 40.783917 | 22.7293599 | green  | small  |
+-------+--------------+----------+-----------+------------+--------+--------+

还有一些具有特征的列,但这些列仅用于过滤。

同时我确实尝试获取 nth 行,虽然有点慢,但似乎有效

SET @a = 0;
select * from `locations` where (@a := @a + 1) % 200 = 0

使用 random() 也可以,但也有点慢。

Edit2:原来在 table 上添加邮政编码很容易。有了这个,按邮政编码分组似乎会给人一种不错的视觉效果。唯一的问题是,有大约 3000 个不同邮政编码的非常大的区域,只得到 100 个可能会导致其中许多显示在一个地方,因此可能需要在 PHP.

中进一步处理

Edit3,在评论中回答@RickJames 的问题,使它们集中在一个地方:

  1. 请定义“均匀分布”——在纬度上均匀分布?没有两个彼此“接近”吗?等等
    • “均匀分布”这个词选错了。我们只想显示该区域的一些位置,这些位置并非都在一个地方
  2. “区域”是矩形吗?六边形?还是 gerrymandered 国会选区?
    • 它们可以粗略地认为是矩形,但这应该无关紧要。我错过了重要的事情,我们还需要显示多个区域的位置。区域可能彼此远离或相邻(但不重叠)。在这种情况下,我们希望将 100 个样本分配到各个区域。
  3. “每个区域100个”是固定的吗?或者它可以是“大约 100”
    • 它不是固定的,它在 100 左右,但如果它看起来不好看,我们可以更改它
  4. table 上有 AUTO_INCREMENT id 吗?数字有差距吗?
    • 是的,有一个 AUTO_INCREMENT id 并且可以有间隙
  5. 问题是否已从“每个区域 100 个”更改为“每个邮政编码 1 个”?
    • 不,问题还是一样,“每个区域显示 100 个,但不是所有区域都在同一个地方”,如何做到这一点并不重要
  6. 输出中的总行数和所需行数是多少?
    • 总行数取决于区域和标准,一个区域最多可达 40k。如果总数超过 1000,我们希望回退显示随机的 100。如果 1000 或更少,我们可以显示所有
  7. 每次 运行 查询时都需要不同的样本吗?
    • 相同样本或不同样本,即使具有相同的标准也可以
  8. 您愿意在 table 中添加一列吗?
    • 这不取决于我,但如果我有充分的论据,那么很可能我们可以添加一个新专栏

这是一种可能满足目标的方法。

  1. 预处理 table,制作新的 table,以去除“重复”项目。
  2. 如果新 table 足够小,对其进行全面扫描可能就足够快了。

至于“重复”,将此视为发现两个项目落在同一位置的粗略方法:

 SELECT  ROUND(latitude * 5),
         ROUND(longitude * 3),
         MIN(id) AS id_to_keep
     FROM tbl
     GROUP BY 1,2

可以向上(或向下)调整“5”和“3”,以保留更多(或更少)的 ID。 “5”和“3”因 lat/lng 的排列方式不同而不同;该比率可能适用于大多数温带纬度。 (在赤道附近使用相同的数量,在更高的纬度使用更大的比例。)

有一个小缺陷...彼此非常接近的两个项目可能跨越了 ROUNDs 所创建的边界。

原来有多少行table?上面的查询生成了多少行? ( SELECT COUNT(*) FROM ( ... ) x; )