laravel 数据查询(集合)

Inner join:

$arr = [];
$str = 'age = ?';
$arr[] = '18';
$str = ' and x = ? and y = ?';
$arr[] = 'x';
$arr[] = 'y';
$list_temp = DB::table('account_info')
    ->join('users','users.account_nu','=','account_info.account_nu')
    ->whereRaw($str, $arr)
    ->orderBy('user_id', 'DESC')
    ;
$list_temp->where('created_at', '>=', $start_time);
$list = $list_temp->get();
//循环 $list 直接 使用 ->属性 获取值即可,
//连表也是 所以如果有相同的字段最好命名别名。
foreach($list as $v){
     $user_id = $v->user_id; // 表account_info的 user_id字段
     $LOGIN = $v->country; // 表users的country字段
}

应用别名:

$list_temp = DB::table('account_info as ai')
    ->join('MT4_USERS as mu','mu.LOGIN','=','ai.mt4_account')
    ->whereRaw($strWhere, $arrWhere)
    ->orderBy('ai.user_id', 'DESC')
    ;
//或者
User::from('user as u')->join('comments as c','u.id','=','c.user_id')    // 未测试

join ON 判断的同时 添加 and 过滤:
使用 join 然后 where , sql 类似: select * from A LEFT JOIN B ON A.id=B.id where A.id > 100 AND B.age<100;
但是有的时候我们希望sql 类似:select * from A LEFT JOIN B ON A.id=B.id AND B.age<100 where A.id > 100;
即 AND 在 ON 之后那么 代码举例:

DB::table('users as u')
->select('u.user_id','c.class')
->leftJoin('class as c', function($join)
{
    $join->on('c.user_id', '=', 'u.user_id')
    ->on('c.status', '=', '2');
})
->get();

hasOne:
hasOne 用于 一对一 例如 user 表 hasOne phone
使用的时候直接 User::find(1)->phone 。 如果只是获取某个用户的 phone 这么用没问题,但是如果批量获取用户的phone 这样就不合适,因为每次获取都会
执行sql : 类似 select * from phone where user_id = $id;
所以应当使用 with

with(渴求式加载):

$data = User::with('phone')->get();

$data = User::with(['phone' => function ($query) {
    $query->where('title', 'like', '%first%');
}])->get();

使用 循环 $data 如果获取phone 直接 $v->phone 即可,但是这样查询结果不能因为关联表的值影响 $data 值数量
例如 select * from user inner join phone on user.id = phone.user_id where phone.number like ‘189%’;
因为 使用 with 的sql 是先 查询所有的 user 然后结果再放到 in 条件里 给 phone 类似:
select * from user where XX; user_id 值为 1,2,3,4 然后再 select * from phone where user_id IN (1,2,3,4); 再将值和 前面的值整合。
所以想要phone 的条件影响 user 的值集合是做不到的。可以使用 whereHas

whereHas:

$list = AccountInfo::whereHas('users',function ($query) use($start_time,$end_time){
    if($start_time){
        $query->where('created_at', '>=', $start_time);
    }
    if($end_time){
        $query->where('created_at', '<=', $end_time);
    }
})->whereRaw($str, $arr)->orderBy('user_id', 'DESC')->get();

即 whereHas 相当于使用 where exists
使用的时候 循环 foreach($list as $v) 然后 ->AccountInfo 的字段,如果需要 users 的字段值就需要 $v->users->+users的字段,但是这里就会产生一个sql(非渴求式)
所以如果还想要 关联表的 值 那么还是使用 DB::table(‘a’)->join 即 inner join 好了

指定查询字段:

//使用all :
AccountInfo::all(['user_id','user_name']);
//使用get:
AccountInfo::where('user_id','<','10')->get(['user_id','user_name']);
//使用select
AccountInfo::where('user_id','<','20')->select(['user_id','user_name'])->get();

使用 chunk:

AccountInfo::orderBy('user_id','desc')->chunk(100,function($accounts){
   foreach ($accounts as $account){
       var_dump($account->toArray());
   }
});

打印sql 类似执行了循环分页,一页 100 默认主键升序排序,可以自定义 orderBy. 也可以添加where 等条件

判断是否有结果:
使用 eloquent 获取结果,不能使用 empty 或者 is_null 等来判断,因为如果没有结果,empty 也是 false
因为返回的空结果 也是 Illuminate\Database\Eloquent\Collection 对象实例
Eloquent 已经封装了几个判断方法:

$result = Model::where(...)->get();

if ($result->first()) { }
if (!$result->isEmpty()) { }
if ($result->count()) { }

laravel lockForUpdate sharedLock

//考虑当有并发更新此行数据的时候使用。
//insert ,delete 等sql操作不需要使用, 读取(select)的时候使用 lockForUpdate 或者 sharedLock。
//举例:
DB::table('user')->where('age', '>', 18)->lockForUpdate()->get();
//或者
User::where(xxx)->lockForUpdate()->first();
//共享锁:
DB::table('users')->where('votes', '>', 100)->sharedLock()->get();
//lockForUpdate 相当于 sql:
select * from users where id =2 for update
//sharedLock 相当于 sql:
select * from users where id=2 lock in share mode;

注意:锁要使用在 事务中,查询的行务必使用索引,避免全表扫描,这样会导致锁整个表,而不是某一行。
使用锁,这个表的引擎必须是 innodb.
具体可以查看 : mysql 悲观锁 乐观锁 和共享锁。
orderBy 排序:

$list->orderBy('id','asc');
根据 id 升序排序
多个字段排序则:
$list->orderBy('id','asc')->orderBy('name','desc');
自定义排序规则:(使用 orderByRaw)
$list->orderByRaw('CONVERT(chinese_name USING gbk) ASC');  // 中文排序

sum 多个字段或者自定义规则:

DB::table('user')->select(['sum(age)','sum(score)'])->groupBy('user_id'); 

原生 sql select 或者其它通用语句:

$a = DB::select("SELECT user_id,user_name FROM account_info;");
var_dump($a);
返回:
array (size=1)
  0 =>
    object(stdClass)[293]
      public 'user_id' => int 3
      public 'user_name' => string 'aa' (length=2)
通用语句:(只会返回 true/false)
DB::statement("set SESSION sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';");

复杂 sql 举例:(left join ,自定义 select,使用DB::raw , 使用 IFNULL ,select 里面套 select )

$list_temp = DB::table('account_info')
    ->leftJoin('user as us','us.account_nu','=','account_info.account_nu')
    ->whereRaw($str, $arr)
    ->orderBy('user_id', 'DESC')
;

$count = $list_temp->count();

$list = $list_temp
    ->select([
        'account_info.account_nu as account_nu',
        'account_info.chinese_name as chinese_name',
        'account_info.account_type as account_type',
        'us.BALANCE as BALANCE',
        'us.CREDIT as CREDIT',
        'us.EQUITY as EQUITY',
        'us.MARGIN as MARGIN',
        'us.LEVERAGE as LEVERAGE',
        'us.REGDATE as REGDATE',
        DB::raw('IFNULL((SELECT SUM(`trades_going_long`.`VOLUME`) from `trades` as `trades_going_long` where `trades_going_long`.`account_nu` = `account_info`.`account_nu` AND `trades_going_long`.`CMD` = 0 GROUP BY `trades_going_long`.`account_nu`),0) as `going_long`'),
        DB::raw('IFNULL((SELECT SUM(`trades_going_short`.`VOLUME`) from `trades` as `trades_going_short` where `trades_going_short`.`account_nu` = `account_info`.`account_nu` AND `trades_going_short`.`CMD` = 1 GROUP BY `trades_going_short`.`account_nu`),0) as `going_short`'),
        DB::raw('IFNULL((SELECT SUM(`trades_profit`.`PROFIT`) from `trades` as `trades_profit` where `trades_profit`.`account_nu` = `account_info`.`account_nu` AND `trades_profit`.`CMD` IN (0,1) GROUP BY `trades_profit`.`account_nu`),0) as `profit`'),
    ])
    ->skip($start)
    ->take($pageSize)
    ->get()
;

mysql 严格模式 only_full_group_by 等 (mysql 5.6 + 默认开启的)
有的时候报错 Syntax error or access violation 1055 ‘xxx’ isn’t in GROUP BY xxx 这种通常是因为开启了 only_full_group_by 引起的
所以我们可以修改 my.cnf

[mysqld]
sql_mode=IGNORE_SPACE,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

然后重启 mysql 服务
/etc/init.d/mysql restart
如果还是报错: 那么可能是 laravel 框架的限制,即 修改 config/database.php mysql 链接下的 strict 配置,为 false
如果 为 true ,laravel 会执行:

protected function strictMode()
{
    return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'";
}

持续更新…

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值