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

单表多字段排序异常:酒店价格降序排序逻辑修正诉求

解决方案:按酒店最大/最小价格正确排序

核心问题在于直接关联hotel_price表会返回每个酒店的多条价格记录,排序时无法自动按酒店维度取到对应极值(升序取最小、降序取最大)。双字段排序无效是因为关联后的数据是多对一结构,排序仅对所有价格记录生效,而非聚合后的酒店维度结果。

正确实现思路

需要先按酒店维度聚合出排序所需的价格极值,再基于这个聚合值完成排序。以下提供两种可行方案:

方案1:关联子查询获取聚合价格

通过子查询预计算每个酒店的目标价格,再关联主表进行排序:

// 重写排序类型判定方法
public function getOrderByType(): ?string
{
    return in_array($this->fieldSort, ['price_asc', 'price_desc'], true) 
        ? $this->fieldSort 
        : null;
}
$query = self::getActive();
$query->select([self::tableName() . '.*']);

$sortType = $filter->getOrderByType();
if ($validate && $sortType) {
    // 确定聚合函数:升序取最小,降序取最大
    $aggFunc = $sortType === 'price_asc' ? 'MIN' : 'MAX';
    // 子查询生成每个酒店的目标价格数据集
    $subQuery = (new \yii\db\Query())
        ->select(['hotel_id', "{$aggFunc}(price) as target_price"])
        ->from('hotel_price')
        ->groupBy('hotel_id');
    
    // 关联聚合结果表
    $query->leftJoin(
        ['price_agg' => $subQuery], 
        self::tableName() . '.id = price_agg.hotel_id'
    );
    // 按聚合后的价格排序
    $query->orderBy([
        'price_agg.target_price' => $sortType === 'price_asc' ? SORT_ASC : SORT_DESC
    ]);
}

方案2:聚合函数+分组排序

如果查询仅需酒店主表数据,可直接在排序中使用聚合函数,配合分组确保每个酒店仅返回一条记录:

// 修改排序字段生成逻辑
public function getOrderBy(): array
{
    if (!in_array($this->fieldSort, ['price_asc', 'price_desc'], true)) {
        return [];
    }
    
    $aggFunc = $this->fieldSort === 'price_asc' ? 'MIN' : 'MAX';
    $sortOrder = $this->fieldSort === 'price_desc' ? SORT_DESC : SORT_ASC;
    
    return [
        "{$aggFunc}(hotel_price.price)" => $sortOrder
    ];
}
$query = self::getActive();
$query->select([self::tableName() . '.*']);

if ($validate && !empty($filter->getOrderBy())) {
    $query->joinWith('hotelPrice');
    // 必须按酒店ID分组,确保每个酒店仅返回一条主表记录
    $query->groupBy(self::tableName() . '.id');
    $query->orderBy($filter->getOrderBy());
}

原双字段排序无效原因

ORDER BY hotel_price.id DESC, hotel_price.price DESC 仅对所有关联后的价格记录排序,但框架(推测为Yii)在处理主表查询时会自动去重,最终排序依据的是关联后匹配到的第一条价格记录,而非酒店维度的最大价格,因此无法满足需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:30:56