项目当中经常用到复杂SQL带有子查询,而Laravel的查询构造器并没有直接提供转化成子查询的方法,或者说尽管提供了方法,可是给出来的例子却不太具体,对刚上手的新手来说非常不友好,本文章主要是聊一聊Laravel如何构造各种带有子查询的SQL。

首先,Laravel一般实现子查询的两种方式:

1、toSql()+getQuery()+raw()方法:

  1. toSql()方法的作用是为了获取不带有binding 参数的SQL,也就是说带问号的SQL
select * from `rooms` where `rooms`.`project_id` = ?
  1. getQuery()方法的作用是为了获取binding参数并代替toSql()获得SQL的问号,从而得到完整的SQL
select * from `rooms` where `rooms`.`project_id` = 3
  1. raw()的作用是直接把SQL套进Laravel的查询构造器中
  `$sql = 'select * from `rooms` where `rooms`.`project_id` = 3';
  $resultSql = DB::table('DB::raw($sql as room')->toSql();`   

那么你就能获得SQL:

select * from (select * from `rooms` where `rooms`.`project_id` = 3) as room

注意:直接使用SQL不限于raw(),还有whereRaw()

2、使用查询构造器一些自带的闭包

User ::whereIn( 'id' , function ($query){ $query->select ( 'user_id' ) -> from ( 'admin_user' ) -> whereIn( 'type' , [ '1' , '2' ]); }) -> get();

可以获得的SQL:

select * from `user` where `id` in (select `user_id` from `admin_user` where `type` in (1, 2));

类似这种闭包实现子查询的,还有whereExists、where等等。

PHP代码:

    $ipCountObject = new \Model\BlacklistIpCountDate();
    $ipCountObj = $ipCountObject->selectRaw("sum(attack_count) AS attack_times, ip")->where('attack_count', '>', '0')->whereBetween('data', ['2017-10-10', '2017-10-11'])->groupBy('ip');
    $totalObj = DB::table( DB::raw("({$ipCountObj->toSql()}) as sub, blacklist_attack_ip"))->mergeBindings($ipCountObj->getQuery())->select('attack_ip', 'country', 'province', 'city', 'line', 'info_update_time AS attack_time', 'attack_times'); //toSql获得的sql有?,需要填入变量
    $totalObj = $totalObj->where('blacklist_attack_ip.attack_ip', '=', 'sub.ip')->get();

可获得SQL:

SELECT
    `attack_ip`,
    `country`,
    `province`,
    `city`,
    `line`,
    `info_update_time` AS `attack_time`,
    `attack_times` 
    ( SELECT sum( attack_count ) AS attack_times, ip FROM `blacklist_ip_count_date` WHERE `attack_count` > 0 AND `date` BETWEEN '2017-10-10' AND '2017-10-11' GROUP BY `ip` ) AS sub,
    blacklist_attack_ip 
WHERE
    `blacklist_attack_ip`.`attack_ip` = `sub`.`ip`

这两种方法要灵活应用,第一种基本是通用于子查询在任何地方,而第二种是只适用于与where相关的位置。当然个人建议是统一写法,如果你在项目中用了第一种,那么你就应该坚持where的子查询也用第一种方便,而不是混合第一第二种方法使用。除此之外,Laravel 查询构造器也提供了其他的闭包,例如join,lefeJoin,rightJoin等,但是经过个人的测试,这些闭包并不能实现子查询的。

概述:项目当中经常用到复杂SQL带有子查询,而Laravel的查询构造器并没有直接提供转化成子查询的方法,或者说尽管提供了方法,可是给出来的例子却不太具体,对刚上手的新手来说非常不友好,本文章主要是聊一聊Laravel如何构造各种带有子查询的SQL。 准备:首先,Laravel一般实现子查询的两种方式:1、toSql()+getQuery()+raw()方法:toSql()方法的作用是为了获取不带 Springboot就不用多介绍了吧,相信搜索到这篇文章的人都是Springboot熟手了。 LDAP(Light Directory Access Portocol),它是一款标准的轻量级目录访问协议。从其它地方搬来一些它的简介如下: 目录是一个为查询、浏览和搜索而优化的数据库,它采用树状结构组织数据,类似于文件目录一样 目录数据库与关系数据库不同,它有优异的读性能,但是写入性能差,并且没有事务处理、回滚等复杂功能,不适合存储频繁修改的数据 所以,LDAP天生是用来查询的,就像它的名字 Laravel 的 Query Builder 为执行数据库查询提供了一个干净简单的接口。它可以用来进行各种数据库操作,例如: Retrieving records - 检索记录 Inserting new records -...