What “type” do I specify in addCase to return a column?

扶醉桌前 提交于 2019-12-02 08:32:02

问题


I'm trying to get a query working using a case statement, and can't figure out how to get the case to return a column value instead of a constant. I have the query working perfectly, except that the column names I'm providing for the results are being quoted or otherwise mishandled by Cake or maybe PDO somewhere down in a layer that I can't dig my way through. I got as far down as bindValue, but none of the documentation I encountered along the way tells me how to do this.

I have found this example comment:

$statement->bindValue(1, 'a title');
$statement->bindValue(2, 5, PDO::INT);
$statement->bindValue('active', true, 'boolean');
$statement->bindValue(5, new \DateTime(), 'date');

but in all these cases, the value provided is a constant. I need to pass in a string that is the name of the column that I want returned.

I tried both 'string' (resulted in quoted column name) and 'integer' (resulted in 0). I tried PDO::FETCH_COLUMN (seemed highly unlikely, but looked like the next best bet from http://php.net/manual/en/pdo.constants.php, and easy to try it...). I tried 'literal', inspired by the way you can put literal strings into expressions (resulted in Error: unknown type "literal"). That error message led me to src/Database/Type.php, but nothing in there helped me either.

So, I'm pretty much stumped. Here's a simple version of the code I have (leaving out a couple of conditions and unrelated columns):

$query = $this->Games->find();
$team_id = $query->newExpr()->addCase(
    [$query->newExpr()->eq('Games.status', 'home_default')],
    ['home_team_id', 'away_team_id'],
    ['string', 'string']
);
$defaulting = $query
    ->select([
        'id' => $team_id,
        'count' => 'COUNT(Games.id)',
    ])
    ->where([
        'Games.status IN' => ['home_default', 'away_default'],
    ])
    ->group('id')
    ->toArray();

This generates this SQL:

SELECT
    (CASE WHEN Games.status = 'home_default'
        THEN 'home_team_id' ELSE 'away_team_id' END) AS `id`,
    COUNT(Games.id) AS `count`
FROM games Games
WHERE Games.status in ('home_default','away_default')
GROUP BY id

Note that THEN 'home_team_id' ELSE 'away_team_id' END should be simply THEN home_team_id ELSE away_team_id END. This will then allow me to read the list of ids of teams that have defaulted games along with the number of games they defaulted.


回答1:


By default the values passed to the second argument of QueryExpression::addCase() are being treated as to be converted to literal values, not as identifiers. If you need the latter, then you should use an expression, an IdentifierExpression.

use Cake\Database\Expression\IdentifierExpression;

// ...

$team_id = $query->newExpr()->addCase(
    [
        $query->newExpr()->eq('Games.status', 'home_default')
    ],
    [
        new IdentifierExpression('Games.home_team_id'),
        new IdentifierExpression('Games.away_team_id')
    ]
);

Also ditch the third argument in this case, you don't want the values to be string literals (for expressions the types would be ignored anyways).



来源:https://stackoverflow.com/questions/33383845/what-type-do-i-specify-in-addcase-to-return-a-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!