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

Laravel 8 Eloquent关联过滤:匹配日期的关联数据查询优化

解决方案

1. 定义带日期匹配的专属关联关系

把日期匹配逻辑直接封装到关联方法里,既能避免重复写闭包,也能让Laravel更高效处理关联查询:

public function websiteRevenueMatchingDate()
{
    return $this->hasMany(WebsiteRevenue::class, 'website_id', 'website_id')
        ->whereColumn('website_revenue.date', 'website_shares_dynamic.date');
}

public function websiteMeasureMatchingDate()
{
    return $this->hasMany(WebsiteMeasure::class, 'website_id', 'website_id')
        ->whereColumn('website_measure.date', 'website_shares_dynamic.date');
}

查询时直接调用这个关联即可:

$queryResult = WebsiteShareDynamic::with(['websiteRevenueMatchingDate', 'websiteMeasureMatchingDate'])
    ->whereIn('website_shares_dynamic.id', $maxWSD)
    ->orderBy('website_shares_dynamic.date', 'DESC')
    ->get();

2. 用子查询预加载减少连接开销

如果直接的表连接性能还是差,可以换成子查询预加载的方式,避免大表关联的开销:

$queryResult = WebsiteShareDynamic::query()
    ->whereIn('website_shares_dynamic.id', $maxWSD)
    ->orderBy('website_shares_dynamic.date', 'DESC')
    ->with([
        'websiteRevenue' => function ($query) {
            $query->whereColumn('website_revenue.date', function ($sub) {
                $sub->select('date')
                    ->from('website_shares_dynamic')
                    ->whereColumn('website_shares_dynamic.id', 'website_revenue.website_id');
            });
        },
        'websiteMeasure' => function ($query) {
            $query->whereColumn('website_measure.date', function ($sub) {
                $sub->select('date')
                    ->from('website_shares_dynamic')
                    ->whereColumn('website_shares_dynamic.id', 'website_measure.website_id');
            });
        }
    ])
    ->get();

3. 必须加索引(性能提升核心)

不管用哪种查询方式,索引缺失都是性能慢的核心原因,给以下字段创建联合索引:

  • website_revenue表:(website_id, date)
  • website_measure表:(website_id, date)
  • website_shares_dynamic表:(id, date)(如果id是主键已有索引,至少给date单独加索引)

创建索引的SQL示例:

CREATE INDEX idx_website_revenue_website_date ON website_revenue(website_id, date);
CREATE INDEX idx_website_measure_website_date ON website_measure(website_id, date);

为什么whereHas没效果?

whereHas的作用是筛选主模型(只保留存在符合条件关联的主模型记录),而不是过滤预加载的关联数据。你需要的是预加载时只返回匹配date的关联记录,所以whereHas不适用,必须用with的闭包来约束关联模型的查询范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:16:11