获取另一个表中不存在的所有项目

Posted

技术标签:

【中文标题】获取另一个表中不存在的所有项目【英文标题】:Get all items that do not exist in another table 【发布时间】:2020-08-17 18:14:57 【问题描述】:

我正在使用Laravel Framework 6.16.0,我有两个表,logoscompanies

标志:

        Schema::create('logos', function (Blueprint $table) 
            $table->bigIncrements('id');
            $table->integer('companies_id')->default('999999');
            $table->string('logo_path')->nullable($value = true); // path to the logo image
            $table->timestamps();
        );

公司:

        Schema::create('companies', function (Blueprint $table) 
            $table->bigIncrements('id');
            $table->string('symbol'); // AAPL
            $table->string('name'); // company name such as Apple Inc.
            $table->timestamps();
        );

型号:

class Logo extends Model

    protected $table = 'logos';

    protected $guarded = ['id'];

    public function company()
    
        return $this->belongsTo(Company::class, 'companies_id');
    

class Company extends Model

    protected $table = 'companies';

    protected $guarded = ['id'];


我想获取logo-table 中没有徽标且徽标尚未更新为90 days 的所有符号。

我尝试了以下方法:

        $symbolsWithoutLogos = DB::table('companies')
            >leftJoin('logos', 'companies.id', '=', 'logos.companies_id')
            ->whereDate('logos.updated_at', Carbon::now()->subDays(90))
            ->whereNull('companies.logo_image')
            ->orderBy('name', 'ASC')
            ->get('companies.*');

此查询结果:

select `companies`.* from `companies` left join `logos` on `companies`.`id` = `logos`.`companies_id` where date(`logos`.`updated_at`) = ? order by `name` asc

但是,即使我的公司表有足够的记录,我在运行此查询时也没有得到结果:

任何建议我做错了什么?

感谢您的回复!

【问题讨论】:

我认为您应该更正您提供给我们的信息。因为首先,我看到的是“logo_path”列而不是“logo_image”列,正如您在下面的构建器中所写的那样。其次,在原始 mysql 查询中,我没有看到“logo_image”或“logo_path”。最后,您谈到获取没有徽标但最后更新徽标至少 90 天前的“符号”,这是矛盾的。 【参考方案1】:

您可以使用 Eloquent 来实现这一点,而不是使用左连接和 DB 外观。

我猜 Company 和 Logo 之间的关系是 1:1 或 1:n。如果我们假设它是 1:1,那么您的查询将如下所示:

Company::whereHas('logo', function($query) 
    return $query->where('date', '<', Carbon::now()->subDays(90));
)->orWhereDoesntHave('logo')->...

您应该检查:Querying relationship absence

只要我们遵循 Laravel 命名约定,我们不需要指定表名,Laravel 会从模型名中找出来。

标志模型应该是这样的:

class Logo extends Model

    // protected $table = 'logos'; 
    // not necessary, Laravel already knows to use logos table

    protected $guarded = ['id'];

    public function company()
    
        // return $this->belongsTo(Company::class, 'companies_id');
        // no need to specify foreign key if we follow naming convention
        // foreign key should be foreign_model_singular_id
        // in this case it is company_id
        return $this->belongsTo(Company::class);
    

Company 模型也不需要指定表名,它已经知道它应该是 companies

公司模式:

class Company extends Model

    // protected $table = 'companies';

    protected $guarded = ['id'];

    public function logo()
    
        return $this->hasOne(Logo::class);
    

请检查 $guarded 和 $fillable 属性是如何工作的。如果只有 id 设置为受保护,那么所有其他属性都是不受保护的,不确定这是否是您的意图。

完整的查询应该是:

Company::whereHas('logo', function($query) 
    return $query->where('updated_at', '<', Carbon::now()->subDays(90));
)->orWhereDoesntHave('logo')
->orderBy('name', 'ASC')
->get();

【讨论】:

请查看我对这两个模型的更新问题。【参考方案2】:

->whereDate('logos.updated_at' whereDate 仅比较 dateTime 列的日期部分...尝试使用 carbon 中的 toDateString() ...

  $symbolsWithoutLogos = DB::table('companies')
            ->leftJoin('logos', 'companies.id', '=', 'logos.companies_id')
                ->whereDate('logos.updated_at', Carbon::now()->subDays(90)->toDateString())
                ->whereNull('companies.logo_image')
                ->orderBy('name', 'ASC')->select('companies.*')
                ->get();

【讨论】:

以上是关于获取另一个表中不存在的所有项目的主要内容,如果未能解决你的问题,请参考以下文章

从一个表中选择 Laravel 5.1 中另一个表中不存在的所有记录

如何从一个表中获取另一表中不存在的行

如何获取另一个表中不存在的表的记录?

如何从一个表中选择另一张表中不存在的所有记录?

如何从一个表中选择另一张表中不存在的所有记录?

删除一个表中存在而另一个表中不存在的数据?