Doctrine CASE WHEN THEN ELSE NULL

Posted

技术标签:

【中文标题】Doctrine CASE WHEN THEN ELSE NULL【英文标题】: 【发布时间】:2017-06-12 10:44:26 【问题描述】:

我有一个存储库函数,我想使用 CASE WHEN THEN ELSE,但原则不允许在 ELSE 中使用 NULL。当然,我用谷歌搜索了,但我找不到如何避免它的答案。

public function countAverageOdd($user) 
    return $this->getEntityManager()
                    ->createQuery('
                            SELECT
                                avg(
                                    CASE
                                        WHEN p.homeAway = \'h\' AND p.moneyline IS NOT NULL THEN m.home
                                        WHEN p.homeAway = \'d\' AND p.moneyline IS NOT NULL THEN m.draw
                                        WHEN p.homeAway = \'e\' AND p.moneyline IS NOT NULL THEN m.away
                                        WHEN p.homeAway = \'h\' AND p.spread IS NOT NULL THEN s.home
                                        WHEN p.homeAway = \'e\' AND p.spread IS NOT NULL THEN s.away
                                        WHEN p.homeAway = \'h\' AND p.total IS NOT NULL THEN t.over
                                        WHEN p.homeAway = \'e\' AND p.total IS NOT NULL THEN t.under
                                    ELSE NULL
                                    END
                                    )
                            FROM
                                AppBundle:Predictions p
                                LEFT JOIN p.moneyline m
                                LEFT JOIN p.spread s
                                LEFT JOIN p.total t
                            WHERE p.user = :user ')
                    ->setParameter(":user", $user)
                    ->setMaxResults(1)
                    ->getSingleScalarResult();

错误: [语法错误] 第 0 行,第 900 列:错误:意外的“NULL”

https://github.com/doctrine/doctrine2/issues/3160

doctrinebot 于 2013 年 5 月 22 日发表评论

问题以“无法修复”的解决方案关闭

请给我建议。

【问题讨论】:

【参考方案1】:

我通过传入空值作为参数来绕过 Doctrines 逻辑检查。这是一个 hack,但它似乎是唯一有效的方法。

public function countAverageOdd($user) 
    return $this->getEntityManager()
                    ->createQuery('
                            SELECT
                                avg(
                                    CASE
                                        WHEN p.homeAway = \'h\' AND p.moneyline IS NOT NULL THEN m.home
                                        WHEN p.homeAway = \'d\' AND p.moneyline IS NOT NULL THEN m.draw
                                        WHEN p.homeAway = \'e\' AND p.moneyline IS NOT NULL THEN m.away
                                        WHEN p.homeAway = \'h\' AND p.spread IS NOT NULL THEN s.home
                                        WHEN p.homeAway = \'e\' AND p.spread IS NOT NULL THEN s.away
                                        WHEN p.homeAway = \'h\' AND p.total IS NOT NULL THEN t.over
                                        WHEN p.homeAway = \'e\' AND p.total IS NOT NULL THEN t.under
                                    ELSE :null
                                    END
                                    )
                            FROM
                                AppBundle:Predictions p
                                LEFT JOIN p.moneyline m
                                LEFT JOIN p.spread s
                                LEFT JOIN p.total t
                            WHERE p.user = :user ')
                    ->setParameters(array(":user"=> $user,":null"=>NULL))
                    ->setMaxResults(1)
                    ->getSingleScalarResult();

【讨论】:

我可以在下周一试一试,我会发布结果。【参考方案2】:

另一个技巧是使用NULLIF,即supported。 例如

CASE WHEN WHEN p.homeAway = \'h\' THEN 'xyz' ELSE NULLIF(1,1) END

从https://github.com/doctrine/orm/issues/5801#issuecomment-336132280得到这个

谢谢!

【讨论】:

【参考方案3】:

结帐myql case operator documentation。 ELSE 是可选的,所以你可以删除它

public function countAverageOdd($user) 
    return $this->getEntityManager()
                    ->createQuery('
                            SELECT
                                avg(
                                    CASE
                                        WHEN p.homeAway = \'h\' AND p.moneyline IS NOT NULL THEN m.home
                                        WHEN p.homeAway = \'d\' AND p.moneyline IS NOT NULL THEN m.draw
                                        WHEN p.homeAway = \'e\' AND p.moneyline IS NOT NULL THEN m.away
                                        WHEN p.homeAway = \'h\' AND p.spread IS NOT NULL THEN s.home
                                        WHEN p.homeAway = \'e\' AND p.spread IS NOT NULL THEN s.away
                                        WHEN p.homeAway = \'h\' AND p.total IS NOT NULL THEN t.over
                                        WHEN p.homeAway = \'e\' AND p.total IS NOT NULL THEN t.under

                                    END
                                    )
                            FROM
                                AppBundle:Predictions p
                                LEFT JOIN p.moneyline m
                                LEFT JOIN p.spread s
                                LEFT JOIN p.total t
                            WHERE p.user = :user ')
                    ->setParameter(":user", $user)
                    ->setMaxResults(1)
                    ->getSingleScalarResult();

【讨论】:

也许我回答得太快了,我没有检查 Doctrines DQL 是否真的支持,但我会这样做。您可以从 symfony 分析器中发布相应的 可运行查询 吗? dql 的另一种方法是将其设置为native doctrine query,这应该不是问题,因为您只返回单个标量结果 学说需要else

以上是关于Doctrine CASE WHEN THEN ELSE NULL的主要内容,如果未能解决你的问题,请参考以下文章

case when

case when then[转]

SQL中case when then用法

oracle数据库,对每个月份进行分类获取对应月份的对应内容,case...when... 的使用

SQL语句中case,when,then的用法

请教一下数据库case when then end空值问题