laravel eloquent JOIN ON 多个条件

Posted

技术标签:

【中文标题】laravel eloquent JOIN ON 多个条件【英文标题】:laravel eloquent JOIN ON multiple condition 【发布时间】:2015-05-17 18:02:13 【问题描述】:

我有一个表调用bank,它存储国家银行名称、代码等

我有一个表调用 site_banks,它存储银行帐户、银行持有人姓名和外国 bank_id,它们指的是 bank

我有一个表调用deposit_records,它存储了存款时间、存款收据、状态等以及引用site_banks的外国bank_id /p>

对于deposit_records,status字段,值为1表示成功

现在我想计算每个 site_banks

的总收入

但我不希望每一行 site_banks 调用一个查询来计数,这将有很多 sql 查询调用

所以我想我可以使用 join,下面是 site_banks 模型文件,scopeGroupAllSiteBanksByBranch 是我要收集所有 site_banks 的地方,加入SUM,返回数组

但即使我也有大约 200 个 site_banks 行,很多 deposit_records 行是 status = '1',但是 scopeGroupAllSiteBanksByBranch 总是只返回一行,我不明白为什么,我复制 sql 查询在 mysql 中运行,结果相同,只返回 1 行。

<?php

use Illuminate\Database\Eloquent\SoftDeletingTrait;

class SiteBanks extends \LaravelBook\Ardent\Ardent 

    use SoftDeletingTrait;

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'site_banks';

    protected $dates = ['deleted_at'];

    protected $fillable = array('bank_id', 'bank_name', 'bank_account', 'bank_holder', 'bank_username', 'bank_password', 'min_deposit', 'max_deposit', 'daily_max_deposit');

    public static $rules = array(
        'bank_id' => 'required|exists:banks,id',
        'bank_name' => 'required|min:1',
        'bank_account' => 'required|min:1|numberonly',
        'bank_holder' => 'required|min:1',
        'bank_username' => 'required|min:1',
        'bank_password' => 'required|min:1',
        'min_deposit' => 'required|fund',
        'max_deposit' => 'required|fund',
        'daily_max_deposit' => 'required|fund',
    );

    public function bank() 
        return $this->belongsTo('Banks', 'bank_id');
    

    public function transactions() 
        return $this->hasMany('Deposit', 'bank_id', 'id');
    

    public function transactionsDone() 
        return $this->hasMany('Deposit', 'bank_id', 'id')->where('status', '=', 1);
    

    public function transactionsBanned() 
        return $this->hasMany('Deposit', 'bank_id', 'id')->where('status', '=', 2);
    

    public function transactionsPending() 
        return $this->hasMany('Deposit', 'bank_id', 'id')->where('status', '=', 0);
    

    public function setBankPasswordAttribute($value) 
        $this->attributes['bank_password'] = Crypt::encrypt($value);
    

    public function getBankPasswordAttribute() 
        return Crypt::decrypt($this->attributes['bank_password']);
    

    public function scopeGetAvailableBanks($query) 
        $query->where(DB::raw("(current_deposit < daily_max_deposit) OR (current_deposit IS NULL) OR (DATE(last_deposit) != DATE(NOW()) OR last_deposit IS NULL) OR (DATE(last_deposit) = DATE(NOW()) && current_deposit < daily_max_deposit)"));
        $query->groupBy('bank_id')->orderBy('id', 'ASC');
    

    public function scopeGroupAllSiteBanksByBranch($query) 
        $bank = \SiteBanks::withTrashed()
            ->leftJoin('deposit_records', function($q) 
                $q->on('deposit_records.bank_id', '=', 'site_banks.id');
                $q->where('deposit_records.status', '=', 1, 'and');
            )
            ->select(array('site_banks.*', DB::raw('SUM(`deposit_records`.`deposit_amount`) AS `total_income`')))
            ->get();
//        $bank = \SiteBanks::withTrashed()->get();
        $bank->load('bank');

        $banks = array();
        foreach($bank as $key => $var) 
            $arr = array();

            $arr = $var->toArray();
            $arr['income'] = $var->total_income;
            $banks[$var->bank->bank_name][] = $arr;
        

        return $banks;
    


SQL 查询

选择site_banks.*, SUM(deposit_records.deposit_amount) AS total_income from site_banks left join deposit_records on deposit_records.bank_id = site_banks.iddeposit_records.status = '1'

var_dumpscopeGroupAllBanksByBranch

的结果
array (size=1)
  'BANKNAME' => 
    array (size=1)
      0 => 
        array (size=20)
          'id' => int 1
          'bank_id' => int 4
          'bank_name' => string 'BANKNAME' (length=6)
          'bank_account' => string '123456789' (length=9)
          'bank_holder' => string 'ACCOUNT HOLDER NAME' (length=11)
          'bank_username' => string 'username' (length=8)
          'bank_password' => string 'hehethisispassword' (length=18)
          'min_deposit' => string '400.00' (length=6)
          'max_deposit' => string '9999.99' (length=7)
          'daily_max_deposit' => string '25500.00' (length=8)
          'last_deposit' => string '2015-02-05 03:04:00' (length=19)
          'current_deposit' => string '0.00' (length=4)
          'created_by' => int 1
          'updated_by' => null
          'created_at' => string '2015-02-04 08:21:16' (length=19)
          'updated_at' => string '2015-02-04 08:21:16' (length=19)
          'deleted_at' => null
          'total_income' => string '1722.00' (length=7)
          'bank' => 
            array (size=7)
              ...
          'income' => string '1722.00' (length=7)

【问题讨论】:

【参考方案1】:

这里是解决方案。您可以加入多个条件。

$query = self::select('websites.id','websites.website_url','cron_tracking_details.cron_type');
    $query = $query->leftJoin('cron_tracking_details',function ($join)
        $join->on(function ($queryone)
            $queryone->on('websites.id','=','cron_tracking_details.website_id');
            $queryone->where('cron_tracking_details.cron_type','=',"sitemap_create");
            $queryone->Where('cron_tracking_details.cron_date','<','2020-11-19');
        );
    );
    $query = $query->orderBy('cron_tracking_details.id','desc');
    $query = $query->limit(1);
    return $query = $query->get();

这段代码将像这样准备查询。

select `websites`.`id`, `websites`.`website_url`, `cron_tracking_details`.`cron_type` from `websites` left join `cron_tracking_details` on (`websites`.`id` = `cron_tracking_details`.`website_id` and `cron_tracking_details`.`cron_type` = ? and `cron_tracking_details`.`cron_date` < ?) order by `cron_tracking_details`.`id` desc limit 1

【讨论】:

【参考方案2】:

你可以按照代码解决你的问题

SQL 查询

LEFT JOIN bookings  
           ON rooms.id = bookings.room_type_id AND (bookings.arrival = ? OR bookings.departure = ? )

Laravel 多条件连接

 ->join('bookings', function($join) use ($key1, $key2)

    $join->on('rooms.id', '=', 'bookings.room_type_id');
    $join->on(function($query) use ($key1, $key2)
            
             $query->on('bookings.arrival', '=', $key1);
             $query->orOn('departure', '=',$key2);
            );

)

【讨论】:

【参考方案3】:
public function scopeGroupAllSiteBanksByBranch($query) 
        $bank = \SiteBanks::withTrashed()
            ->leftJoin('deposit_records', function($q) 
                $q->on('deposit_records.bank_id', '=', 'site_banks.id');
                $q->where('deposit_records.status', '=', 1, 'and');
            )
            ->select(array('site_banks.*', DB::raw('SUM(`deposit_records`.`deposit_amount`) AS `total_income`')))
            ->groupBy('site_banks.id')
            ->get();

我找到了解决方案,groupBy('site_banks.id') 然后一切就绪。

【讨论】:

以上是关于laravel eloquent JOIN ON 多个条件的主要内容,如果未能解决你的问题,请参考以下文章

Laravel eloquent join 与三个表

Laravel Eloquent LEFT JOIN WHERE NULL

Laravel Eloquent Join vs Inner Join?

Laravel Eloquent 关系——相当于 MYSQL “join”

Laravel Eloquent ORM 中的 join()->where()

mysql 加入 ON 和 AND 到 laravel eloquent