2016-11-10 51 views
1

この種のCOALESCE()文をクエリビルダに書き込むにはどうすればよいですか?CakePHP 3 - クエリビルダーでCOALESCE(...)を書くには?

SQL

SELECT COALESCE(n.value, p.value) AS value 
FROM nodes n 
LEFT JOIN parents p ON p.id = n.parent_id 

PHP

私は子供と親の両方の値を取得し、結果セットを通過し、ちょうど子供1が空の場合、親のいずれかを使用することができ、クエリ自体にそれを組み込むよりエレガントな方法があれば、私はそれを好むでしょう。

$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

私は別のテストを行なったし、代わりに2つのテーブルのnameフィールドを選択し、それはちょうど私が(彼らはカラム名として評価されません)機能に入力された実際の文字列を返します。

return $q->select([ 
    'value' => $q->func()->coalesce([ 
     'Nodes.name', 
     'Parents.name' 
    ]) 
]); 

返されるエンティティはあります

'value' => 'Nodes.name' 

だから私の新しいquestio nは、テーブル/フィールド名として文字列を評価するクエリビルダを取得する方法ですか?

+1

は注意 – rjdown

+0

COALESCEもORMによってサポートされています:http ://api.cakephp.org/3.3/class-Cake.Database.FunctionsBuilder.html#_coalesce – burzum

+0

@rjdownありがとう、私は質問を更新しました。 – BadHorsie

答えて

3

ケーキのcoalesce()関数は、パラメータをフィールドとして評価することができませんでした。フィールド名の実際の文字列を返すだけでした。

代わりに手動でCOALESCEステートメントを作成して作業しました。(それがすべてであなたの質問を助けることではない!)[値] AS `COALESCE(n.value、p.value)がこれを書い好ましい方法であることを

// 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(); 
1

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(); 

これは、この関数を呼び出すためにどのようにコアの単体テストをチェック動作しない場合。

+0

ありがとう* burzum *。私は残念ながらそれを働かせることはできません。私はいくつかの問題を発見しました。現時点ではフィールド名をフィールドとして評価するための 'coalesce()'を得ることができません。それは単に私が配列に入れた文字列を与えるだけです。更新された質問をご覧ください。 – BadHorsie