雄辩的haversine公式没有按预期工作

Posted

技术标签:

【中文标题】雄辩的haversine公式没有按预期工作【英文标题】:Eloquent haversine formula is not working as expected 【发布时间】:2019-08-23 16:09:25 【问题描述】:

我陷入了半正弦公式,在我的情况下它仍然不起作用。

在以下示例中,我获取了用户及其所有关系。我需要根据与搜索地址的距离来检索用户。按照下面的说明,我收到以下错误:未找到列:1054 Unknown column 'distance' in 'having clause'

“activity_latitude”和“activity_longitude”都存储在我开始获取数据的主用户表中。我做错了什么?

$q = self->whereNull("deleted_at")->where("group_id", 1)
        ->with([
            "data", 
            "rating",
            "pendingcontents",
            "openinghours",
            "openinghours.dayofweek",
            "openinghoursexceptions",
            "isopeningtime",
            "contents",
            "contents.translation", 
        ]);

$q->selectRaw('( 3959 * acos( cos( radians(?) ) *
                cos( radians( activity_latitude ) )
                * cos( radians( activity_longitude ) - radians(?)
                ) + sin( radians(?) ) *
                sin( radians( activity_latitude ) ) )
                ) AS distance', [$geocodedAddress[0], $geocodedAddress[1], $geocodedAddress[0]])
->havingRaw("distance < ?", [$radius]);

那么我还需要按距离订购。

总结一下,我只需要根据距离取值,按距离排序即可。

我不明白为什么这个版本有效...使用相关表格及其坐标

$q->whereHas('businessdata', function ($q) use ($filtro, $geocodedAddress, $radius) 
                $q->selectRaw('( 3959 * acos( cos( radians(?) ) *
                    cos( radians( activity_latitude ) )
                    * cos( radians( activity_longitude ) - radians(?)
                    ) + sin( radians(?) ) *
                    sin( radians( activity_latitude ) ) )
                    ) AS distance', [$geocodedAddress[0], $geocodedAddress[1], $geocodedAddress[0]])
                ->havingRaw("distance < ?", [$radius]);
            );

【问题讨论】:

@thmsdnnr 虽然works in mysql @thmsdnnr 我想检查需要 2 秒 :-( 如果是我,我会创建一个存储过程来计算距离,然后调用它两次——一次在 SELECT 子句中,一次在 WHERE 子句中。这似乎违反直觉,但我怀疑这比在 HAVING 子句中调用别名要快。如果性能很关键,那么您还可以考虑创建一个边界框,但这将在别处讨论。 确实...感谢您的更正! (删除上面关于 MySQL 不允许在 HAVING 子句中使用别名的错误评论,如 MS SQL)。 @thmsdnnr 随意删除误导性的 cmets。 【参考方案1】:

为您分配了一个别名(距离)。

您可以简单地使用来自

orderBy()

https://laravel.com/docs/5.8/queries#ordering-grouping-limit-and-offset

这将允许您使用距离别名。即

$q->selectRaw('( 3959 * acos( cos( radians(?) ) *
                cos( radians( activity_latitude ) )
                * cos( radians( activity_longitude ) - radians(?)
                ) + sin( radians(?) ) *
                sin( radians( activity_latitude ) ) )
                ) AS distance', [$geocodedAddress[0], $geocodedAddress[1], $geocodedAddress[0]])
->havingRaw("distance < ?", [$radius])
->orderBy("distance");

您还可以为方向传递第二个可选参数(默认为'asc')。

【讨论】:

但是之前还有一个问题需要解决:column not found: 1054 Unknown column 'distance' in 'have Clause' - 似乎距离别名不存在或被解释为列名.我需要的只是按距离和按距离排序 尝试将havingRaw() 换成where。 have 用于过滤组,而 where 用于过滤行。从您的查询来看,您似乎在过滤之前没有对任何内容进行分组? 我用了 where 但还是同样的问题...距离不存在

以上是关于雄辩的haversine公式没有按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

CakePHP 2.2.4 无法使用 HAVING 子句和计算字段对结果进行分页 - Haversine 公式

Java中的Haversine公式产生不正确的结果

Rails expect(controller).not_to have_received(:get_from_database) 没有按预期工作

Haversine 公式的不同结果

Tupper 在 C++ 中的自引用公式没有按预期工作?

Haversine 公式无法正常工作