[英]CakePHP 3 - How to write COALESCE(…) in query builder?
如何在查詢構建器中編寫這種COALESCE()
語句?
SQL
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'
所以我的新問題是如何讓查詢構建器將字符串評估為表/字段名稱?
我無法讓 Cake 的coalesce()
函數將參數作為字段進行評估,它只是返回字段名稱的實際字符串。
我通過手動創建COALESCE
語句來讓它工作。
// Create the query object first, so it can be used to create a SQL expression
$query = $this->Nodes->find();
// Modify the query
$query
->select([
'id',
'value' => $query->newExpr('COALESCE(Nodes.value, Parents.value)')
])
->where(['Nodes.id' => $id])
->contain('Parents')
->first();
CakePHP 的coalesce()
使用以下格式來區分字段名稱和文字值:
'value' => $q->func()->coalesce([
'User.last_name' => 'identifier',
', ',
'User.first_name' => 'identifier'
])
上面的代碼應該產生類似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/一個明顯的例子。
見http://book.cakephp.org/3.0/en/orm/query-builder.html#using-sql-functions
沒試過,但我猜是:
$child = $this->Nodes->find()
->select(['id', 'value'])
->where(['Nodes.id' => $id])
->contain([
'Parents' => function ($q) {
return $q->select(['value' => $query->func()->coalesce([
/* Fields go here... I think. :) */
])]);
}
])
->first();
如果這不起作用,請檢查核心的單元測試如何調用此函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.