在无需使用ORM无需定义数据库模型的情况下,用联表查询方法就可以连表查询多表数据。

支持一对一,多对一,一对多,多对多等多种数据表关联。

并且在默认设定和联表作用域下,查询语法更加简洁易懂,也不用像一些框架或库一样需要嵌杂原生的SQL的来实现(Query语法和原生SQL混杂在一起不伦不类,不如直接用SQL)。

示例:查询主题1及其发布者与评论信息

$db->post->join('user')->on('user_id', 'id')->select('name')->with('comment')->get(1)
// 生成并执行的SQL
SELECT `post`.*,`user`.`name` AS `user_name` FROM `post` LEFT JOIN `user` ON `post`.`user_id` = `user`.`id` WHERE `post`.`id` = '1'
SELECT * FROM `comment` WHERE `post_id` = '1'

例中关联到了post user comment 3个表,其中post作为主表,user是join从表,comment是with从表。

post表与user表是多对一关系,一个post只有一个user发表者,一个user能发表多个post主题。

post表与comment表是一对多关系,一个post有多条comment评论,一条comment只属于一个post主题。

先主表post join user表查询数据,表之间使用on方法关联字段,得到查询数据后使用with逻辑联表方法查询comment数据,表之间关联使用默认设定,然后组合数据返回。

另一个示例:查找积分大于0的用户,及其在2017-10-01后发表的主题。

$db->user->select('id', 'name')// 查找用户id name
   ->sub('account')->where('score', '>', 0)// 查找用户积分score大于0的记录
   ->with('post')->select('id', 'title')->where('time', '>', '2017-10-01') //查找主表用户2017-10-01后发布主题的id和标题
   ->find(); //执行查询
// 生成并执行的SQL
SELECT `id`,`name` FROM `user` WHERE `id` IN (SELECT `user_id` FROM `account` WHERE `score` > '0') 
SELECT `id`,`title`,`user_id` FROM `post` WHERE `user_id` IN ('1','2','3','5') AND `time` > '2017-10-01'

例中关联到了user account post 3个表,其中user作为主表,account是子查询从表,post是with从表。

此连表查询示例的作用域:$db->usersub('account') 之间是主表user作用域,sub('account')with('post') 之间是从表account作用域,with('post')find() 之间是从表post作用域,在作用域内whereselect order limit等方法不需要显式的指定表名,因为作用域确定了这些方法是作用于那张表,并在生成SQL时自动处理。

此联表查询示例用到的默认设定:在例中user表和account post表是如何关联的?在我们并没有显式的指定的情况下,会默认使用主表的id字段与从表中字段名为主表名+id的字段关联,此例中恰好account post表中都有user_id字段,所以我们可以直接使用默认设定,如不用默认设定我们也可以使用on方法来指定关联字段。

1 join方法

生成原生SQL JOIN语句联表查询多表数据.

通常用一对一和多对一表关系场合

一对一:查询用户信息与其帐号积分信息(一个用户只有一个积分帐号表)

$db->user->join('account')->select('score')->get($user_id);
SELECT `user`.*,`account`.`score` AS `account_score` FROM `user` LEFT JOIN `account` ON `user`.`id` = `account`.`user_id` WHERE `user`.`id` = '1'

多对一:查询最近10个主题以及发布者信息(一个用户可以发布多个主题)

$db->post->order('id', true)->limit(10)->join('user')->on('user_id', 'id')->select('id', 'name')->find();
SELECT `post`.*,`user`.`id` AS `user_id`,`user`.`name` AS `user_name` FROM `post` LEFT JOIN `user` ON `post`.`user_id` = `user`.`id` ORDER BY `post`.`id` DESC LIMIT 10
2 with方法

使用逻辑联表查询多表数据。

通常用于一对多和多对多表关系场合

在默认优化条件下只需要1+1次SQL查询,先查主表数据,然后根据主表数据where in查询从表数据,最后逻辑组合2表数据。

查询一个用户及其最近10个主题

$db->user->with('post')->order('id', true)->limit(10)->get($user_id)
SELECT * FROM `user` WHERE `id` = '1' LIMIT 1
SELECT * FROM `post` WHERE `user_id` = '1' ORDER BY `id` DESC LIMIT 10

查询主题以及回复评论第1页

$db->post->with('comment')->page(1)->get($post_id)
SELECT * FROM `post` WHERE `id` = '1' LIMIT 1
SELECT * FROM `comment` WHERE `post_id` = '1' LIMIT 0,30
3 relate方法

通常用于多对多表关系场合,并且有一个关系表存储2个表的对应关系。

在默认优化条件下只需要1+1+1次SQL查询,先查主表数据,在查关系表数据,然后根据关系表数据查询从表数据,最后逻辑组合3表数据。

查询一个用户及其最近收藏书签的主题,其中bookmark书签表是关系表保存user和post多对多的映射关系。

$db->user->relate('post')->on('bookmark')->get($user_id);
SELECT * FROM `user` WHERE `id` = '1' LIMIT 1
SELECT `user_id`, `post_id` FROM `bookmark` WHERE `user_id` IN ('1')
SELECT * FROM `post` WHERE `id` IN ('2','3','5')
4 sub方法

生成原生SQL子查询语句联表查询主表数据。

子查询通常只做为主表的过滤条件,用户不需要其本身数据。

查询最新一个主题的作者的信息。

$db->user->sub('post')->order('id', ture)->get()
SELECT * FROM `user` WHERE `id` IN (SELECT `user_id` FROM `post` ORDER BY `id` DESC)  LIMIT 1
5 union方法

使用原生SQL union语法联表查询主表数据。

union用于表结构相同的多个表。

$db->table1->union('table2')->union('table3')->find()

results matching ""

    No results matching ""