You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony QueryBuilder判断select count返回值是否为null/空的方法

COUNT() 聚合函数的特性是即使子查询无匹配行,也会返回数字 0 而非 NULL,所以你不需要处理 NULL 场景,只要过滤两个统计值同时为 0 的行即可。如果你的业务场景中子查询不是COUNT聚合、确实可能返回NULL,可以用COALESCE函数把NULL转为0再判断。

以下是两种可行的实现方案:

方案1:用HAVING子句直接过滤统计结果

这种写法改动最小,直接在原有查询基础上增加HAVING条件排除两个统计值同时为0的行即可:

$qb
            ->select([
                'c.id as c_id',
                'c.name as c_name',
                sprintf('(SELECT COUNT(t) FROM %s t WHERE t.example = c.example) as t_total',
                    t::class),
                sprintf('(SELECT COUNT(z) FROM %s z WHERE z.example = c.secondExample) as z_total',
                    z::class),
            ])
            ->from(c::class, 'c')
            // 新增条件:排除t_total和z_total同时为0的行
            ->having('t_total != 0 OR z_total != 0')
            ->getQuery()
            ->getResult();

注意:如果你的Doctrine版本要求聚合类别名必须配合GROUP BY使用,额外补充->groupBy('c.id')即可。

方案2:用EXISTS子查询优化性能

如果表数据量较大,第一种方案需要全量统计COUNT再过滤会有性能损耗,可改用EXISTS判断是否存在匹配行,子查询找到第一条匹配就会终止,不需要统计总数,执行效率更高:

$qb
            ->select([
                'c.id as c_id',
                'c.name as c_name',
                sprintf('(SELECT COUNT(t) FROM %s t WHERE t.example = c.example) as t_total',
                    t::class),
                sprintf('(SELECT COUNT(z) FROM %s z WHERE z.example = c.secondExample) as z_total',
                    z::class),
            ])
            ->from(c::class, 'c')
            // 新增WHERE条件:两个关联表至少有一个存在匹配行
            ->where(
                $qb->expr()->orX(
                    $qb->expr()->exists(sprintf('SELECT 1 FROM %s t WHERE t.example = c.example', t::class)),
                    $qb->expr()->exists(sprintf('SELECT 1 FROM %s z WHERE z.example = c.secondExample', z::class))
                )
            )
            ->getQuery()
            ->getResult();

内容的提问来源于stack exchange,提问作者Valera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:57:06