Mysql 需要了解此sql的帮助吗

Mysql 需要了解此sql的帮助吗,mysql,sql,Mysql,Sql,我试图破译这个SQL语句。具体来说,位置z、位置o、位置a的含义是什么。在这种情况下,z o和a是什么意思?困惑的: SELECT o.zip_code FROM locations z, locations o, locations a WHERE z.zip_code = #{zip_code} AND z.zip_code = a.zip_code AND (3956 * (2 * ASIN(SQRT( POWER(SIN(((z.latitude-o.latitude)

我试图破译这个SQL语句。具体来说,位置z、位置o、位置a的含义是什么。在这种情况下,z o和a是什么意思?困惑的:

SELECT o.zip_code
FROM locations z, locations o, locations a

WHERE z.zip_code = #{zip_code}
AND z.zip_code = a.zip_code
AND (3956 * (2 * ASIN(SQRT(
        POWER(SIN(((z.latitude-o.latitude)*0.017453293)/2),2) +
        COS(z.latitude*0.017453293) *
        COS(o.latitude*0.017453293) *
        POWER(SIN(((z.longitude-o.longitude)*0.017453293)/2),2)
    )))) <= #{distance}

这些是表别名

Aliases are powerful for complex queries that need to 
    use the same table twice but in different ways.
在此查询中,FROM子句为表名指定别名。别名location z意味着location表在查询的其他地方可以称为z。例如,z.zip_代码与location.zip_代码相同。这将保存此查询中的键入

这是英语的简写

 locations AS z, locations AS o, locations AS a
或者换句话说,它们是别名

原作者没有在代码中一直写位置,而是选择将它们别名为速记,在本例中是z o和a

此外,由于他三次使用同一个表,因此别名允许他区分每个表

z保存使用{zip_code}引用点查找的记录

a和z是相同的记录

o包含{distance}地理距离内的所有记录

简言之:

它可以找到位于半径为{distance}围绕z的圆圈中的所有邮政编码

顺便说一下,3956是地球的半径,大约以英里为单位,所以你得到的结果以英里为单位


如果您对此感兴趣,您可以在

上阅读更多内容。它似乎试图选择zipcode${zip_code}的{distance}范围内的所有zipcode

我认为这篇文章很好地解释了正是为了这个目的而使用的余弦定律:


z、o和a是别名,因为同一个表被连接了三次。

这些是so表名的简写,而不是键入locations.zip_code。它缩写为a.zip_code


在这个例子中,它也有帮助,因为同一个表是从3次中选择的。

这是位置表自身的笛卡尔积,两次。由于查询将同一个表与其自身连接,因此需要重命名每个部分,以便稍后在查询中可以唯一地标识它们。z、 o和a是这些名字

看看例子二,看看发生了什么。除了在这种情况下,有两个笛卡尔积而不是一个。都在同一张桌子上

查询本身可能会非常慢,因为它正在进行双笛卡尔乘积,它将创建一个临时表,其中n是位置表中的行数,m是列数,有n³行和3m列

编辑以回应评论。我对此不是很肯定,但在阅读了您的查询后,我相信它正在查找与另一个邮政编码有一定距离的所有邮政编码。它看起来像第三个笛卡尔积a,甚至没有使用,因此您可以将查询简化为:

SELECT o.zip_code
FROM locations z, locations o

WHERE z.zip_code = #{zip_code}
AND (3956 * (2 * ASIN(SQRT(
        POWER(SIN(((z.latitude-o.latitude)*0.017453293)/2),2) +
        COS(z.latitude*0.017453293) *
        COS(o.latitude*0.017453293) *
        POWER(SIN(((z.longitude-o.longitude)*0.017453293)/2),2)
    )))) <= #{distance}
但这仍然有一个笛卡尔乘积。我们最好能把它处理掉:

SELECT zip_code
FROM locations

WHERE (3956 * (2 * ASIN(SQRT(
        POWER(SIN((((SELECT latitude FROM locations WHERE zip_code = #{zip_code})-latitude)*0.017453293)/2),2) +
        COS((SELECT latitude FROM locations WHERE zip_code = #{zip_code})*0.017453293) *
        COS(latitude*0.017453293) *
        POWER(SIN((((SELECT longitude FROM locations WHERE zip_code = #{zip_code})-longitude)*0.017453293)/2),2)
    )))) <= #{distance}

MySQL可能会很好地优化这些字母,它们是表别名,本质上是SQL开发人员给位置表的昵称。同一个locations表使用三个不同的名称连接在一起,因为它是一个表,在locations表的不同用途之间有区别

位置已重命名为z, 位置已重命名为o, 位置已重命名为

将z更改为位置1 将o更改为位置2
如果这有助于您阅读SQL,请将a改为locations3

有没有更快的方法来实现这一点的想法?感谢您的帮助。如果您使用postgresql,请尝试使用mysql空间扩展或postgis,它们都支持空间索引@Lisa我编辑了我的文章,并提出了一些改进速度和cpu负载的想法