如何使用Eloquent按字段空值数量对查询结果排序?
问题描述
我有一个可用的Eloquent查询:
$users = User::whereNotNull('name') ->orWhereNotNull('phone') ->orWhereNotNull('email') ->get();
我的数据库数据如下:
id | name | phone | email 1 | Luc | null | null 2 | Bob | null | bob@g.com 3 | null | null | null 4 | Bil | +2121 | bil@g.com
当前查询会返回id为1、2、3的记录,但我希望按字段空值数量排序,将空值最多的用户排在前面,示例中期望顺序为3、1、2。请问是否可以用withCount()和orderBy()实现?
回答
withCount()主要用于统计关联模型的数量,并不适合直接计算当前模型自身字段的空值数量。不过我们可以通过原生SQL计算空值计数结合orderBy()来实现需求,这种方式比强行套用withCount()更直接高效。
实现代码
$users = User::whereNotNull('name') ->orWhereNotNull('phone') ->orWhereNotNull('email') ->selectRaw('*, ( CASE WHEN name IS NULL THEN 1 ELSE 0 END + CASE WHEN phone IS NULL THEN 1 ELSE 0 END + CASE WHEN email IS NULL THEN 1 ELSE 0 END ) AS null_count') ->orderByDesc('null_count') ->get();
代码说明
selectRaw()中的CASE语句逐个判断字段是否为空,为空则累加1,最终得到null_count(当前记录的空值字段总数)。orderByDesc('null_count')会让空值数量最多的记录排在最前面,完全匹配你的期望顺序:id=3(3个空值)→ id=1(2个空值)→ id=2(1个空值)。
关于withCount()的补充
如果硬要使用withCount(),需要构造无关关联或嵌套子查询,这属于舍近求远的操作,完全没必要。withCount()的设计初衷是处理关联模型计数场景(比如统计用户发布的文章数量),而非当前模型的字段空值统计,所以原生SQL计算是最优方案。
内容的提问来源于stack exchange,提问作者Dessauges Antoine
相关产品推荐
相关产品推荐

