Laravel中如何用whereIn从JSON字段查找重复手机号?
解决Laravel中JSON字段查找重复手机号的问题
原代码的问题主要出在JSON字段的提取方式和子查询分组的逻辑上,以下是修正后的实现方案:
修正思路
- 对JSON字段的
phone值进行正确提取,确保获取到不带引号的纯字符串(MySQL中可使用->>语法) - 子查询中直接使用JSON提取表达式分组,避免别名导致的数据库解析问题
- 主查询的
whereIn参数需要用DB::raw包裹,确保数据库能正确识别JSON路径表达式
修正后的代码
use Illuminate\Support\Facades\DB; // 获取手机号重复的订单记录 $query = Order::query(); return $query->select('id', 'recipient') ->whereNotNull('recipient') ->whereIn(DB::raw("recipient->>'$.phone'"), function ($subQuery) { $subQuery->select(DB::raw("recipient->>'$.phone'")) ->from('orders') ->whereNotNull('recipient') ->groupBy(DB::raw("recipient->>'$.phone'")) ->havingRaw('COUNT(*) > 1'); })->paginate();
关键说明
recipient->>'$.phone':MySQL专属语法,用于提取JSON字段并自动去除字符串引号,等价于JSON_UNQUOTE(JSON_EXTRACT(recipient, '$.phone')),保证获取的是纯净的手机号字符串- 子查询直接用JSON提取表达式分组,避免了分组阶段无法识别字段别名的问题
- 主查询用
DB::raw包裹JSON路径,让Laravel直接传递原生SQL表达式给数据库,而非当作普通字段处理
兼容PostgreSQL(可选)
如果使用PostgreSQL数据库,JSON字段提取语法需调整为recipient->>'phone',对应代码替换如下:
// PostgreSQL版本适配 ->whereIn(DB::raw("recipient->>'phone'"), function ($subQuery) { $subQuery->select(DB::raw("recipient->>'phone'")) ->from('orders') ->whereNotNull('recipient') ->groupBy(DB::raw("recipient->>'phone'")) ->havingRaw('COUNT(*) > 1'); })
内容的提问来源于stack exchange,提问作者Leslie Joe
相关产品推荐
相关产品推荐

