前幾天寫了一遍關於laravel分表關聯的查詢,可是我我的以爲還不算完美,因而今天從新看了一下laravel模型的底層代碼,終於寫出我暫時以爲最滿意的代碼-laravel風格,簡潔、優雅是核心。php
下面直接上demo代碼,主要是3個表,一個用戶表,一個是用戶送禮表,送禮表按月分表laravel
user表
id用戶ID
nickname暱稱sql
<?php namespace App\Models; use Eloquent; class User extends Eloquent { }
send_gift_2017_07,send_gift_2017_08 送禮表
id自增主鍵
user_id用戶ID
worth禮物價值
uper_id主播ID(也是用戶表的)
created_at送禮時間數據庫
<?php namespace App\Models; use Eloquent; class SendGift extends Eloquent { //關聯用戶表,外鍵是user_id public function user() { return $this->belongsTo(User::class); } 關聯用戶表 外鍵是uper_id public function uper() { return $this->belongsTo(User::class); } }
如今作一個輸入開始日期和結束日期查看用戶的送禮記錄而且分頁。性能
<?php namespace App\Http\Controllers; use App\Models\SendGift; use DB; use Carbon\Carbon; class IndexController extends Controller { public function index() { // 開始日期,和日期有關的,都建議用內置的carbon處理,很是好用,並且簡潔 $start = Carbon::parse(request('start')); // 結束日期 $end = Carbon::parse(request('end')); // 查詢集合 $queries = collect(); // 循環比較年月,添加每一張表的查詢 for ($i = $start->copy(); $i->format('Y-m') <= $end->format('Y-m'); $i->addMonth()) { $queries->push( DB::table("send_gift_{$i->format('Y_m')}") // 建議都用select查詢字段,SQL儘量的優化性能 ->select('user_id', 'worth', 'uper_id', 'created_at') ->whereBetween('created_at', [$start, $end->tomorrow()]) ); } // 出列一張表做爲union的開始 $unionQuery = $queries->shift(); // 循環剩下的表添加union $queries->each(function ($item, $key) use ($unionQuery) { $unionQuery->unionAll($item); }); // 設置臨時表的名稱,添加臨時表,順序不能反過來,不然用關聯約束會找不到表 $lists = with(new SendGift)->setTable('union_send_gift') // 添加臨時表 ->from(DB::raw("({$unionQuery->toSql()}) as union_send_gift")) // 合併查詢條件 ->mergeBindings($unionQuery) // 關聯約束,不在用戶表的不用查出來 ->has('user') // 按時間倒序 ->orderBy('created_at', 'desc') // 分頁 ->paginate(); // 加載關聯關係 $lists->load([ 'user' => function ($query) { // 關聯查詢也要優化sql $query->select('id', 'nickname'); }, 'uper' => function ($query) { $query->select('id', 'nickname'); } ]); // 測試結果 $lists->each(function ($item, $key) { echo "用戶:{$item->user_id}-{$item->user->nickname}在{$item->created_at->toDateTimeString()}送出了價值{$item->worth}元的禮物給主播:{$item->uper_id}-{$item->uper->nickname}<br>"; }); } }
而後咱們看看SQL。測試
關聯查詢用了渴求式加載,就能有效減小SQL的條數,保證數據庫的性能。優化