欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Laravel 数据库实例教程 —— 使用查询构建器实现对数据库的高级查询

shiping1 的头像
上一节我们简单介绍了如何使用查询构建器数据库进行基本的增删改查操作,这一节我们来探讨如何使用查询构建器实现一些更高级的查询操作。

1、连接查询(join

连接查询指的是将两张表或多张表关联到一起进行查询,获取一个表的行与另一个表的行匹配的数据。常见的连接查询包括内连接(等值连接)、左(外)连接、右(外)连接和交叉连接(完全连接)等。下面这张图形象的展示了这几种连接查询所获取的结果集:

SQL连接查询

下面我们简单演示下内连接和左连接。我们将用户表users和文章表posts关联到一起进行查询,在此之前,我们先创建posts表,其字段及初始值如下:

文章表posts

其中user_id对应users表中的用户id。

1.1 内连接

内连接用于获取两张表结果集的交集部分,我们可以使用查询构建器的join方法进行内连接查询:

$users = DB::table('users')->join('posts','users.id','=','posts.user_id')->get();
dd($users);

显示结果如下:

inner join 查询结果

1.2 左连接

左连接的结果集指定的左表的所有行,如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值(null)。我们使用查询构建器的leftJoin方法进行左连接查询:

$users = DB::table('users')->leftJoin('posts','users.id','=','posts.user_id')->get();
dd($users);

对应的输出结果为:

left join 查询结果

1.3 更加复杂的连接查询

很多时候,连接查询的查询条件往往更为复杂,并不是一个简单的join/leftJoin方法就能搞定的,那么我们如何添加更加复杂的查询条件呢?使用JoinClause代替条件参数:

$users = DB::table('users')->join('posts',function($join){
    $join->on('users.id','=','posts.user_id')
         ->where('posts.id','>',1);
})->get();
dd($users);

输出结果为:

复杂连接查询结果集

2、联合查询(union

联合查询用于将两个或更多查询的结果集组合为单个结果集,该结果集包含联合查询中所有查询的全部行。UNION的结果集列名与UNION运算符中第一个Select语句的结果集的列名相同,另一个Select语句的结果集列名将被忽略,且其他查询字段数必须和第一个相同。Laravel查询构建器中我们使用union方法进行联合查询:

$users = DB::table('users')->where('id','<',3);
$users = DB::table('users')->where('id','>',2)->union($users)->get();
dd($users);

输出结果为:

联合查询结果集

3、where子句

使用查询构建器上的where方法可以添加自定义查询条件,调用该方法需要传入三个参数:第一个列名,第二个是操作符,第三个是比较值:

$user = DB::table('users')->where('name','=','Laravel')->get();
dd($user);

如果操作符为“=”,该语句也可简化为:

$user = DB::table('users')->where('name','Laravel')->get();

输出结果为:

where查询结果集

需要注意的是查询构建器支持方法链,这意味着如果有多个查询条件且这个多个条件是AND连接,可以在get之前使用多个where方法。如果多个条件使用OR连接,可以使用orWhere方法:

$user = DB::table('users')->where('name','Laravel')->orWhere('name','Academy')->get();

对应输出为:

orWhere查询结果集

更多where子句查询条件可查看Illuminate\Database\Query\Builder源码。

4、排序

查询构建器使用orderBy方法对查询结果进行排序:

$users = DB::table('users')->orderBy('id','desc')->get();
dd($users);

根据代码可以看到orderBy方法需要传入两个参数,第一个是排序字段,第二个是排序方向,asc代表升序,desc代表倒序,上述代码输出为:

orderBy查询结果集

5、分组

为了更好地演示分组,我们给数据表posts新增两个字段:cat_idviews,代表分类ID和浏览数:

posts表新增分类ID和浏览数

分组一般用于聚合查询,接下来我们使用groupBy方法对查询结果进行分组,比如我们可以统计每个分类下有几篇文章:

$posts = DB::table('posts')->select('cat_id',DB::raw('COUNT(id) as num'))->groupBy('cat_id')->get();
dd($posts);

输出如下:

groupBy查询结果集

我们还可以使用having方法为分组加上条件,比如我们可以统计总浏览数大于500的分类:

$posts = DB::table('posts')->select('cat_id',DB::raw('SUM(views) as views'))->groupBy('cat_id')->having('views','>',500)->get();
dd($posts);

输出结果为:

加条件的分组查询结果

注意:having中的条件字段必须出现在select查询字段中,否则会报错。

6、分页

查询构建器中使用skiptake对查询结果进行分页,相当于SQL语句中的limit语句:

$posts = DB::table('posts')->skip(0)->take(2)->get();
dd($posts);

对应的输出结果为:

分页查询结果集

  • 业子

    要实现对数据库中姓名排序,应该是如何去做?

  • begin

    跟着教程一点一点学习.赞

  • A就叫我

    发现思路越来越清晰了 [嘻嘻]

  • lds

    看了下 很清楚

  • 黎梅
    1. 黎梅
      select a.id,a.name,a.tags,b.* from pg_program a join(select video_id,count(report_reason) as num from pg_report group by video_id) as b on b.video_id=a.id;
      请问下这个sql语句用model怎么写? [可怜]        
    2. 还有2条评论
    3. 学院君
      说实话 还真没用过 回头我研究下       

    解决了 
    $query=Report::groupBy('video_id')->selectRaw('video_id,count(video_id) as num')->join('pg_program','pg_program.id','=','pg_report.video_id')->selectRaw('pg_program.*');

  • 学院君
    1. 黎梅
      select a.id,a.name,a.tags,b.* from pg_program a join(select video_id,count(report_reason) as num from pg_report group by video_id) as b on b.video_id=a.id;
      请问下这个sql语句用model怎么写? [可怜]        
    2. 还有1条评论
    3. 黎梅
      你用过joinraw吗?       

    说实话 还真没用过 回头我研究下

  • 黎梅
    1. 黎梅
      select a.id,a.name,a.tags,b.* from pg_program a join(select video_id,count(report_reason) as num from pg_report group by video_id) as b on b.video_id=a.id;
      请问下这个sql语句用model怎么写? [可怜]        
    2. 学院君
      这种SQL还是用原生SQL写起来方便 就不要用model了 [嘻嘻]        

    你用过joinraw吗?

  • 学院君
    1. 黎梅
      select a.id,a.name,a.tags,b.* from pg_program a join(select video_id,count(report_reason) as num from pg_report group by video_id) as b on b.video_id=a.id;
      请问下这个sql语句用model怎么写? [可怜]        

    这种SQL还是用原生SQL写起来方便 就不要用model了 [嘻嘻]

  • 黎梅

    select a.id,a.name,a.tags,b.* from pg_program a join(select video_id,count(report_reason) as num from pg_report group by video_id) as b on b.video_id=a.id;
    请问下这个sql语句用model怎么写? [可怜]

  • 学院君
    1. 田先生
      多谢学院       

    感谢大家支持 [呵呵]


来自 http://laravelacademy.org/post/920.html
普通分类: