Laravel使用查询构建器实现对数据库(分组 联合 分页 排序)

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);

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();

 

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

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

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

4、排序

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

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

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

5、分组

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

posts表新增分类ID和浏览数

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

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

 

我们还可以使用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、分页

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

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

时间: 2025-01-29 19:09:08

Laravel使用查询构建器实现对数据库(分组 联合 分页 排序)的相关文章

Laravel查询构建器对数据库增删改查的例子

获取查询构建器很简单,还是要依赖DB门面,我们使用DB门面的table方法,传入表名,即可获取该表的查询构建器: $users = DB::table('users'); 这样我们就获取到了$users表的查询构建器,实际上,底层返回的是Illuminate\Database\Query\Builder的实例,我们对查询构建器的所有操作都是调用该实例对应类上的方法.下面我们就列举查询构建器的一些常用方法,我们还是沿用上一节创建的$users表做演示说明 . 1.新增数据 使用查询构建器的inse

Laravel 5.3 查询构建器方法 where/update 新增 JSON 属性操作语法

从 5.0 版本起 Laravel 就支持 JSON 格式数据的转换,之前这样做的目的只是为了方便业务处理,数据存储在数据库的数据类型依然是 TEXT,但是 MySQL 5.7 版本起开始支持原生的 JSON 数据类型,这将为我们的开发带来极大方便.Laravel 5.3 也为基于 JSON 类型的数据查询和更新引入了新的语法. 假设我们有一个包含 JSON 类型字段的数据表: class CreateContactsTable extends Migration {     public fu

定义查询构建器IFeatureLayerDefinition

在宗地出图,需要实现,只显示某一户人的地块.在ArcMap里,有个定义查询,可只显示过滤后的要素. 在代码中,也比较好实现,使用IFeatureLayerDefinition接口即可. IFeatureLayerDefinition pFeatLyrDef = pFeatureLayer as IFeatureLayerDefinition; pFeatLyrDef.DefinitionExpression = whereClause; axMap.ActiveView.Refresh();

详解SQLite中的查询规划器_数据库其它

 1.0 介绍 查询规划器的任务是找到最好的算法或者说"查询计划"来完成一条SQL语句.早在SQLite 3.8.0版本,查询规划器的组成部分已经被重写使它可以运行更快并且生成更好的查询计划.这种重写被称作"下一代查询规划器"或者"NGQP". 这篇文章重新概括了查询规划的重要性,提出来一些查询规划固有的问题,并且概括了NGQP是如何解决这些问题. 我们知道的是,NGQP(下一代查询规划器)几乎总是比旧版本的查询规划器好.然而,也许有的应用程序在

Effective Java (2) 遇到多个构造器参数时要考虑用构建器

一.背景 对于有多个可选参数的类,我们一般通过什么办法传递参数呢?这里提供了三种办法: ①. 重叠构造器模式 ②. JavaBeans模式 ③. Builder构建器模式 下面我们来分析一下以上三种方法的优势及弊端. 二.重叠构造器模式 重叠构造器模式中第一个构造器中只有必要参数,第二个构造器有一个可选参数,第三个构造器中有两个可选参数,依次类推,最后一个构造器中包含所有可选参数.这种方案可行,但是有较大缺陷. 缺点:当有很多可选参数的时候,客户端代码很难编写,并难以阅读,如果客户端不小心颠倒了

副本构建器

克隆看起来要求进行非常复杂的设置,似乎还该有另一种替代方案.一个办法是制作特殊的构建器,令其负责复制一个对象.在C++中,这叫作"副本构建器".刚开始的时候,这好象是一种非常显然的解决方案(如果你是C++程序员,这个方法就更显亲切).下面是一个实际的例子:   //: CopyConstructor.java // A constructor for copying an object // of the same type, as an attempt to create // a

构建器

为违例编写代码时,我们经常要解决的一个问题是:"一旦产生违例,会正确地进行清除吗?"大多数时候都会非常安全,但在构建器中却是一个大问题.构建器将对象置于一个安全的起始状态,但它可能执行一些操作--如打开一个文件.除非用户完成对象的使用,并调用一个特殊的清除方法,否则那些操作不会得到正确的清除.若从一个构建器内部"掷"出一个违例,这些清除行为也可能不会正确地发生.所有这些都意味着在编写构建器时,我们必须特别加以留意. 由于前面刚学了finally,所以大家可能认为它是

构建器内部的多形性方法的行为

构建器调用的分级结构(顺序)为我们带来了一个有趣的问题,或者说让我们进入了一种进退两难的局面.若当前位于一个构建器的内部,同时调用准备构建的那个对象的一个动态绑定方法,那么会出现什么情况呢?在原始的方法内部,我们完全可以想象会发生什么--动态绑定的调用会在运行期间进行解析,因为对象不知道它到底从属于方法所在的那个类,还是从属于从它衍生出来的某些类.为保持一致性,大家也许会认为这应该在构建器内部发生. 但实际情况并非完全如此.若调用构建器内部一个动态绑定的方法,会使用那个方法被覆盖的定义.然而,产

构建器的调用顺序

构建器调用的顺序已在第4章进行了简要说明,但那是在继承和多形性问题引入之前说的话. 用于基础类的构建器肯定在一个衍生类的构建器中调用,而且逐渐向上链接,使每个基础类使用的构建器都能得到调用.之所以要这样做,是由于构建器负有一项特殊任务:检查对象是否得到了正确的构建.一个衍生类只能访问它自己的成员,不能访问基础类的成员(这些成员通常都具有private属性).只有基础类的构建器在初始化自己的元素时才知道正确的方法以及拥有适当的权限.所以,必须令所有构建器都得到调用,否则整个对象的构建就可能不正确.