CakePHP 2.x 中 SELECT 中表达子查询

问题描述 投票:0回答:1

尽可能抽象,我想表演:

select id,complicatedCalculation as geodistance from User join others having geodistance < 100;

在 CakePHP 2.x 中。实际查询使用聚合,因此我们确实需要having。当数据库是 MySQL 时,这一切都有效,因为该数据库接受 having 子句中的列引用。我们现在正在转向 Postgres,它更严格地实现 SQL 标准并报告

geodistance
不存在。

SQL 中的解决方案是将指令写为

select * from (select id, complicatedCalculation as geodistance from User join others) as sub where geodistance < 100;

但是我不知道如何在 Cake 中表达该子查询。迄今为止我最好的尝试是

$db = $this->User->getDataSource();
$core = [ 'fields' => [ 'id', 'complicatedCalculation as geodistance' ],
        'table' => $db->fullTableName($this->User),
        'join' => (others) ]
$sub_query = $db->buildStatement($core, $this->User);
$result = $this->User->find('all', [
        'fields' => [ 'id', 'geodistance' ],
        'table' => $db->expression($sub_query),
        'alias' => 'zzz',  // not used but PGSQL requires it.
        'conditions' => [ 'geodistance <=' => 100 ]
    ]);

但这会产生以下 SQL(抽象),在日志中报告为错误:

SELECT "User"."id" AS "User__id", complicatedCalculation as geodistance FROM "public"."users" AS "User" LEFT JOIN (others) WHERE "geodistance" <= 100

所以我尝试让 CakePHP 使用表达式作为表是行不通的。我可以让它这样做吗?

建议升级到当前版本的 Cake 的答案不可接受。如果没有其他办法,我们就使用

query()

sql mysql postgresql cakephp
1个回答
0
投票

两者都不是更好。可能他们会以完全相同的方式被处决。来看看

EXPLAIN SELECT ...

真正的问题是必须计算每一行的

geodistance
,并且没有简单的方法可以加快速度。

这里有5种方法

;你的相当于第一个(最差的):查找最近的.

更好的是使用

SPATIAL
索引。这将需要改变数据的存储方式。

另一个相当不错的方法是建立一个“边界框”,然后有2个索引。

该链接中讨论了两种替代方案。

您的查询是“查找 100 以内的所有内容”。该链接谈到“找到 100 内最接近的 N”。

© www.soinside.com 2019 - 2024. All rights reserved.