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