如何在查询生成器中编写这种COALESCE()
语句?
查询语句
SELECT COALESCE(n.value, p.value) AS value
FROM nodes n
LEFT JOIN parents p ON p.id = n.parent_id
PHP语言
我可以检索子值和父值,然后遍历结果集,如果子值为空,则只使用父值,但如果有更优雅的方法将其构建到查询本身中,我会更喜欢这样。
$child = $this->Nodes->find()
->select(['id', 'value'])
->where(['Nodes.id' => $id])
->contain([
'Parents' => function ($q) {
return $q->select('value');
}
])
->first();
if (empty($child->value)) {
$child->value = $child->parent->value;
}
更新1
这就是我目前所拥有的,但它不起作用。
$child = $this->Nodes->find()
->select(['id', 'value'])
->where(['Nodes.id' => $id])
->contain([
'Parents' => function ($q) {
return $q->select([
'value' => $q->func()->coalesce([
'Nodes.value',
'Parents.value'
])
]);
}
])
->first();
退货:
object(Cake\ORM\Entity) {
'id' => (int) 234,
'value' => (float) 0,
'[new]' => false,
'[accessible]' => [
'*' => true
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Nodes'
}
子值是NULL
,父值是1.00
,因此我希望实体值是'value' => (float) 1.00
,但我假设它是从查询中出来的,因为FALSE
转换为(float) 0
。
更新2
似乎将合并的别名设置为已作为普通字段存在的名称不起作用。合并结果需要唯一的字段名。
更新3
我做了另一个测试,从两个表中选择了name
字段,它只返回我输入到函数中的实际字符串(它们不会作为列名计算):
return $q->select([
'value' => $q->func()->coalesce([
'Nodes.name',
'Parents.name'
])
]);
返回的实体具有:
'value' => 'Nodes.name'
因此,我的新问题是如何让查询构建器将字符串作为表/字段名进行计算?
3条答案
按热度按时间8nuwlpux1#
我无法让Cake的
coalesce()
函数将参数作为字段进行计算,它只是返回字段名的实际字符串。我通过手动创建
COALESCE
语句来使它工作。vnjpjtjt2#
CakePHP的
coalesce()
使用以下格式来区分字段名和文字值:上面的代码应该产生类似
Smith, John
的结果。预设行为是将项目视为常值。
请访问https://api.cakephp.org/3.3/class-Cake.Database.FunctionsBuilder.html#_coalesce
文档根本没有很好地解释这一点。H/T到https://www.dereuromark.de/2020/02/06/virtual-query-fields-in-cakephp/是一个清晰的例子。
mec1mxoz3#
请访问http://book.cakephp.org/3.0/en/orm/query-builder.html#using-sql-functions
我还没试过,但我猜是:
如果这不起作用,请检查核心的单元测试如何调用此函数。