有以下数据,三张表:role(角色表)、hero(英雄表)、skill(技能表),我们以英雄联盟的数据做示例
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` int NOT NULL AUTO_INCREMENT,
`Name` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
INSERT INTO `role` VALUES (1,‘战士‘),(2,‘法师‘),(3,‘刺客‘),(4,‘坦克‘),(5,‘射手‘),(6,‘辅助‘);
DROP TABLE IF EXISTS `hero`;
CREATE TABLE `hero` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`title` varchar(45) NOT NULL,
`role_id` int NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
INSERT INTO `hero` VALUES (1,‘赵信‘,‘德邦总管‘,1),(2,‘安妮‘,‘黑暗之女‘,2),(3,‘瑞兹‘,‘符文法师‘,2),(4,‘卡特琳娜‘,‘不祥之刃‘,3);
DROP TABLE IF EXISTS `skill`;
CREATE TABLE `skill` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`passive` varchar(45) NOT NULL DEFAULT ‘0‘,
`hero_id` int NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
INSERT INTO `skill` VALUES (1,‘果决‘,‘1‘,1),(2,‘三重爪击‘,‘0‘,1),(3,‘风斩电刺‘,‘0‘,1),(4,‘无畏冲锋‘,‘0‘,1),(5,‘新月护卫‘,‘0‘,1),(6,‘嗜火‘,‘1‘,2),(7,‘碎裂之火‘,‘0‘,2),(8,‘焚烧‘,‘0‘,2),(9,‘熔岩护盾‘,‘0‘,2),(10,‘提伯斯之怒‘,‘0‘,2),(11,‘奥术专精‘,‘1‘,3),(12,‘超负荷‘,‘0‘,3),(13,‘符文禁锢‘,‘0‘,3),(14,‘法术涌动‘,‘0‘,3),(15,‘曲境折跃‘,‘0‘,3),(16,‘贪婪‘,‘1‘,4),(17,‘弹射之刃‘,‘0‘,4),(18,‘伺机待发‘,‘0‘,4),(19,‘瞬步‘,‘0‘,4),(20,‘死亡莲华‘,‘0‘,4);
有时候我们需要同时获取两张表或三张表或更多表的信息,我们有两种方式:
比如我们要查出英雄是 安妮 的技能有哪些
1.我们可以先在hero表查询到安妮的信息,然后再去skill表查询技能信息,需要两次查询
2.我们可以使用join将两张表关联到一起,通过一次查询获取
简单来说,就是需要同时获取多张表的信息时需要用到sql的join
corss join可以对两张表进行笛卡尔积,任意的两张表或多张表都可以进行笛卡尔连接,哪怕这些表没有任何关系
我们现在对hero表和skill进行corss join
SELECT * FROM hero CROSS JOIN skill;
SELECT * FROM hero,skill;
SELECT * FROM hero JOIN skill;
以上三种形式都可以生成笛卡尔积,产生的结果是两个表的信息合并在一起,数据条数就是两个表条数相乘
果决
技能的那如何将那些不符合我们业务逻辑的记录过滤掉呢?
SELECT * FROM hero CROSS JOIN skill on hero.id = skill.hero_id;
SELECT * FROM hero CROSS JOIN skill WHERE hero.id = skill.hero_id;
此时我们查询到的结果就是符合业务逻辑的
我们直接把上面的 cross join 更改为 inner join
select * from hero inner join skill
查询到的依然是一个笛卡尔积
加上 on 后
select * from hero inner join skill on hero.id = skill.hero_id;
查询到的和cross join加on的结果是一样的。
如下图所示,加了on只有,只会将 hero.id = skill.role_id 的数据挑选出来,错误的结果就被排除掉了
为了说明left join和right join,我们在数据库中插入四条数据
//英雄表新增两个英雄,但是没有对应的技能
INSERT INTO `LOL`.`hero` (`name`, `title`, `role_id`) VALUES (‘艾希‘, ‘寒冰射手‘, ‘5‘);
INSERT INTO `LOL`.`hero` (`name`, `title`, `role_id`) VALUES (‘索拉卡‘, ‘众星之子‘, ‘6‘);
//技能表新增两个技能,但是没有对应的英雄
INSERT INTO `LOL`.`skill` (`name`, `passive`) VALUES (‘阿尔法突袭‘, ‘0‘);
INSERT INTO `LOL`.`skill` (`name`, `passive`) VALUES (‘无极剑道‘, ‘0‘);
select hero.name,skill.name from hero left join skill on hero.id = skill.hero_id;
以上语句查询,我们会得到如下结果:
没有技能的两个英雄,它所对应的技能为null
区别就是left join会包含inner join的结果集,left join就是查询到 hero.id = skill.hero_id 的结果集再加上左表没有匹配到的结果集;left join是更偏重左表的,将左表里面没有匹配到的记录也会加入到结果集中
left join是确保左表中的列是一定存在的
select hero.name,skill.name from hero right join skill on hero.id = skill.hero_id;
以上语句查询,我们会得到如下结果:
所以我们发现right join和left join是相反的,侧重于右表
有时候我们希望左表的记录和右表的记录都出现在结果集里,我们就可以使用outer join
但是我们发现mysql、sqlserver都没有 outer join这个语法,只有 left outer join 和right outer join
left outer join 查询的结果和 left join 一样
right outer join 查询的结果和 right join 一样
那我们应该如何 outer join 呢
答案是使用 union
select hero.name,skill.name from hero left join skill on hero.id = skill.hero_id
union
select hero.name,skill.name from hero right join skill on hero.id = skill.hero_id
上述查询会产生如下结果,这个结果是符合我们预期的
以上就是sql中各种join的语法与使用
原文:https://www.cnblogs.com/xiaoqingtian/p/13681631.html