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

Laravel 10中PostgreSQL查询distinct与orderBy联用报错求助

Laravel 10 + PostgreSQL 中 distinct() 与 orderBy() 共存问题解决

问题背景

使用Laravel 10框架、PostgreSQL数据库时,无法在查询中同时使用distinct()和orderBy(),尝试group_by又出现重复结果,网上方案均无效。查询代码如下:

$property = DB::table('properties')
            ->leftjoin('property_sub_types', 'property_sub_types.id', '=', 'properties.property_sub_type')
            ->leftjoin('property_images', 'properties.id', '=', 'property_images.property_id')
            ->leftjoin('cities', 'cities.id', '=', 'properties.city')
            ->select('properties.name as proName', 'properties.id as pro_id', 'properties.city', 'properties.street', 'property_sub_types.name as subName', 'property_images.image as imgName','cities.name as ctyName','properties.reserve_price','properties.description','properties.possession','properties.ownership','properties.auction_start_date','properties.contact_manager','properties.contact_number', 'properties.updated_at')
            ->where('properties.property_status', 4)
            ->where('properties.status', 1)
            ->where('property_sub_types.status', 1)
            ->orderBy('properties.updated_at')
            ->distinct('properties.id')
            ->paginate(30);

报错信息

SQLSTATE[42P10]: 无效列引用: 7 ERROR: SELECT DISTINCT ON 的表达式必须与初始 ORDER BY 表达式匹配 LINE 1: select distinct on ("properties"."id")

解决方案

原因说明

PostgreSQL的DISTINCT ON语法有强制要求:排序的第一个字段必须和DISTINCT ON指定的字段完全一致,这是报错的核心原因。


方法一:调整排序顺序,符合PostgreSQL规则

把properties.id放在orderBy的首位,再追加你需要的updated_at排序,就能满足DISTINCT ON的要求:

$property = DB::table('properties')
            ->leftjoin('property_sub_types', 'property_sub_types.id', '=', 'properties.property_sub_type')
            ->leftjoin('property_images', 'properties.id', '=', 'property_images.property_id')
            ->leftjoin('cities', 'cities.id', '=', 'properties.city')
            ->select('properties.name as proName', 'properties.id as pro_id', 'properties.city', 'properties.street', 'property_sub_types.name as subName', 'property_images.image as imgName','cities.name as ctyName','properties.reserve_price','properties.description','properties.possession','properties.ownership','properties.auction_start_date','properties.contact_manager','properties.contact_number', 'properties.updated_at')
            ->where('properties.property_status', 4)
            ->where('properties.status', 1)
            ->where('property_sub_types.status', 1)
            ->orderBy('properties.id') // 先按DISTINCT ON指定的字段排序
            ->orderBy('properties.updated_at') // 再按目标字段排序
            ->distinct('properties.id')
            ->paginate(30);

方法二:子查询先去重,再关联排序

如果不想改变最终的排序顺序,可以先通过子查询获取去重后的properties记录,再关联其他表并排序:

$property = DB::table(function($query) {
                $query->select('id', 'name', 'city', 'street', 'reserve_price', 'description', 'possession', 'ownership', 'auction_start_date', 'contact_manager', 'contact_number', 'updated_at', 'property_sub_type')
                      ->from('properties')
                      ->where('property_status', 4)
                      ->where('status', 1)
                      ->distinct('id');
            }, 'properties')
            ->leftjoin('property_sub_types', 'property_sub_types.id', '=', 'properties.property_sub_type')
            ->leftjoin('property_images', 'properties.id', '=', 'property_images.property_id')
            ->leftjoin('cities', 'cities.id', '=', 'properties.city')
            ->select('properties.name as proName', 'properties.id as pro_id', 'properties.city', 'properties.street', 'property_sub_types.name as subName', 'property_images.image as imgName','cities.name as ctyName','properties.reserve_price','properties.description','properties.possession','properties.ownership','properties.auction_start_date','properties.contact_manager','properties.contact_number', 'properties.updated_at')
            ->where('property_sub_types.status', 1)
            ->orderBy('properties.updated_at')
            ->paginate(30);

补充:解决group_by重复问题

用group_by时出现重复,是因为没有正确处理非分组字段。需要确保分组字段是properties.id(唯一标识),同时对关联表的非唯一字段(比如图片)使用聚合函数(如MAX()、MIN())获取唯一值:

$property = DB::table('properties')
            ->leftjoin('property_sub_types', 'property_sub_types.id', '=', 'properties.property_sub_type')
            ->leftjoin('property_images', 'properties.id', '=', 'property_images.property_id')
            ->leftjoin('cities', 'cities.id', '=', 'properties.city')
            ->select(
                'properties.name as proName', 
                'properties.id as pro_id', 
                'properties.city', 
                'properties.street', 
                'property_sub_types.name as subName', 
                DB::raw('MAX(property_images.image) as imgName'), // 用聚合函数取唯一图片
                'cities.name as ctyName',
                'properties.reserve_price',
                'properties.description',
                'properties.possession',
                'properties.ownership',
                'properties.auction_start_date',
                'properties.contact_manager',
                'properties.contact_number', 
                'properties.updated_at'
            )
            ->where('properties.property_status', 4)
            ->where('properties.status', 1)
            ->where('property_sub_types.status', 1)
            ->groupBy(
                'properties.id', 
                'properties.name', 
                'properties.city', 
                'properties.street', 
                'property_sub_types.name', 
                'cities.name', 
                'properties.reserve_price',
                'properties.description',
                'properties.possession',
                'properties.ownership',
                'properties.auction_start_date',
                'properties.contact_manager',
                'properties.contact_number', 
                'properties.updated_at'
            )
            ->orderBy('properties.updated_at')
            ->paginate(30);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:54:55