什么"键入"在addCase中指定返回列吗?

时间:2015-10-28 05:54:23

标签: sql cakephp orm cakephp-3.0 query-builder

我试图使用case语句来查询查询,并且无法弄清楚如何让case返回列值而不是常量。我有完美的查询工作,除了我提供结果的列名称被Cake引用或者错误处理,或者某个地方的某个PDO错误地处理了我无法解决的问题。我和bindValue一样远,但是我在路上遇到的文档都没有告诉我如何做到这一点。

我找到了这个例子评论:

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

但在所有这些情况下,提供的值是常量。我需要传入一个字符串,该字符串是我想要返回的列的名称。

我尝试了'string'(导致引用列名称)和'integer'(结果为0)。我试过PDO::FETCH_COLUMN(似乎非常不可能,但看起来是http://php.net/manual/en/pdo.constants.php的下一个最好的赌注,并且很容易尝试...)。我尝试了'literal',其灵感来自于将文字字符串放入表达式的方式(导致Error: unknown type "literal")。该错误消息让我src/Database/Type.php,但其中没有任何内容帮助我。

所以,我非常难过。这是我所拥有的代码的简单版本(省略了几个条件和不相关的列):

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

这会生成此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

请注意,THEN 'home_team_id' ELSE 'away_team_id' END应该只是THEN home_team_id ELSE away_team_id END。这将允许我阅读已默认游戏的团队ID以及他们默认的游戏数量。

1 个答案:

答案 0 :(得分:4)

默认情况下,传递给QueryExpression::addCase()的第二个参数的值将被视为转换为literal values,而不是identifiers。如果您需要后者,那么您应该使用表达式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')
    ]
);

在这种情况下也抛弃第三个参数,你不希望这些值是字符串文字(对于表达式,类型将被忽略)。