【问题标题】:recursive geometric query : five closest entities递归几何查询:五个最近的实体
【发布时间】:2013-06-28 11:41:07
【问题描述】:

问题是下面描述的查询是否可以在不求助于过程逻辑的情况下完成,也就是说,它可以单独由 SQL 和 CTE 和窗口函数处理吗?我使用的是 SQL Server 2012,但问题不仅限于该引擎。

假设我们有一个包含 250,000 行的全国音乐教师数据库:

  teacherName, address, city, state, zipcode, geolocation, primaryInstrument

其中geolocation 列是具有最佳镶嵌索引的geography::point 数据类型。

用户想要五位离他最近的吉他老师。 如果我们选择任意距离截断,例如 50 英里,则使用窗口函数的查询性能足够好,这样我们就不会选择所有 250,000 行,然后按距离对它们进行排序并取最近的 5 行。

但是,如果用户选择来自不同文化的乐器,例如西塔琴或乌德琴或巴拉莱卡琴,那么任意 50 英里半径截断可能并不总是成功地包含 5 位教师;在她所在的 50 英里范围内可能没有五位此类乐器的老师。

另外,现在假设我们有一个查询,音乐学院向我们发送了 250 名歌手的名单,这些歌手是来年被学校录取的学生,他们希望我们向他们发送最接近的五位为列表中的每个人提供语音教练,以便这些学生可以在到达校园之前安排接受一些指导。我们必须扫描教师数据库 250 次(即扫描地理定位索引),因为这些学生都住在全国不同的地方。

所以,我想知道,对于后一个涉及 250 个学生位置列表的查询,是否有可能编写一个递归查询,其中半径开始很小,例如 10 英里,然后每增加 10 英里迭代,直到达到 100 英里的最大半径或找到所需的五 (5) 名教师?能不能只针对还没有匹配到所需5位老师的学生?

我认为它不能单独使用 SQL 来完成,而必须通过循环和临时表来完成——但也许那是因为我还没有弄清楚如何单独使用 SQL 来完成。

附: primaryInstrument 列也可以减少按距离排序的集合的大小,但为了这个问题,忘记这一点。

编辑:这是一个示例查询。 SINGER(提交的)数据集包含一个具有任意半径的列,以将地理结果限制为较小的子集,但如上所述,该半径可能定义一个可能不包含所需数量的圆(其中心点是学生的地理位置)的老师。有时提供的数据集包含数千个地址,而不仅仅是几百个。

select TEACHERSRANKEDBYDISTANCE.* from
(
select STUDENTSANDTEACHERSINRADIUS.*,
rowpos = row_number() 
over(partition by 
        STUDENTSANDTEACHERSINRADIUS.zipcode+STUDENTSANDTEACHERSINRADIUS.streetaddress 
      order by DistanceInMiles)
from
(
select
SINGER.name, 
SINGER.streetaddress, 
SINGER.city, 
SINGER.state, 
SINGER.zipcode, 
TEACHERS.name as TEACHERname, 
TEACHERS.streetaddress as TEACHERaddress, 
TEACHERS.city as TEACHERcity, 
TEACHERS.state as TEACHERstate, 
TEACHERS.zipcode as TEACHERzip,
TEACHERS.teacherid,
geography::Point(SINGER.lat, SINGER.lon, 4326).STDistance(TEACHERS.geolocation)
            / (1.6 * 1000) as DistanceInMiles
from 
SINGER left join TEACHERS
on 
( TEACHERS.geolocation).STDistance( geography::Point(SINGER.lat, SINGER.lon, 4326))   
     < (SINGER.radius * (1.6 * 1000 ))
 and TEACHERS.primaryInstrument='voice'
) as STUDENTSANDTEACHERSINRADIUS
) as TEACHERSRANKEDBYDISTANCE
where rowpos < 6    -- closest 5 is an abitrary requirement given to us

【问题讨论】:

  • 您能否发布您的查询(可能是一些测试数据),以便我们尝试运行它?我已经在我的桌面上尝试了 ~100000 行,它的性能相对较好(在随机数据上)。我也认为 primaryInstrument 列上的索引可以加快查询速度。
  • 问题是随机数据可能比实际数据表现更好,因为在大都市地区,人口密度要高得多。检索纽约市 50 英里范围内的每位钢琴教师与检索北达科他州法戈(~美国西伯利亚)50 英里范围内的每位钢琴教师有很大不同。
  • 另外主要问题是Top 5是绝对要求,但不可能知道哪个半径将包含5。

标签: sql recursion query-performance sqlgeography


【解决方案1】:

我认为,如果您只需要获得最近的 5 位老师,而不管半径如何,您可以编写类似这样的内容。 Student 在这个查询中会重复 5 次,我不知道你想得到什么。

select
    S.name, 
    S.streetaddress, 
    S.city, 
    S.state, 
    S.zipcode, 
    T.name as TEACHERname, 
    T.streetaddress as TEACHERaddress, 
    T.city as TEACHERcity, 
    T.state as TEACHERstate, 
    T.zipcode as TEACHERzip,
    T.teacherid,
    T.geolocation.STDistance(geography::Point(S.lat, S.lon, 4326))
    / (1.6 * 1000) as DistanceInMiles
from SINGER as S
    outer apply (
        select top 5 TT.*
        from TEACHERS as TT
        where TT.primaryInstrument='voice'
        order by TT.geolocation.STDistance(geography::Point(S.lat, S.lon, 4326)) asc
    ) as T

【讨论】:

  • 您的查询是可行的,并且大部分时间都表现良好。但是乐器越流行,它的速度就越慢。当primaryInstrument非常流行时,例如“钢琴”,在primaryInstrument上过滤时返回的子集有很多行。也许 30% 的音乐老师教钢琴,所以 75,000 行必须按地理距离排序 250 次,这是一个计算值。 primaryInstrument 的不均匀分布是我将该列作为连接上的辅助过滤器而不是主过滤器的原因。 “5个最接近”是交给我的一个困难的完全任意的要求。
  • 嗯,这是一个有趣的问题,但是当我没有你的数据来测试什么是有效的时候,很难得到好的结果:(
  • 接受答案,因为它确实通过回避它解决了不可知的最小半径的主要问题,尽管有性能损失。
  • @Tim 递归检索通常很慢
猜你喜欢
  • 2021-01-22
  • 1970-01-01
  • 2018-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-04
相关资源
最近更新 更多