数据库—连接查询
程序员文章站
2024-03-23 09:01:58
...
1.连接查询
案例:张三、李四等人去商场买了一些物品花了一些钱
案例中应该包括三张表依次是:用户表、订单表、商品表
其中用户表与订单表示一对多的关系、订单表与商品表示多对多的关系
下面通过图解来分析如何建立他们之间的联系:
对于一对多如何建立联系通常是:从表(多表一方)添加外键约束,引用主表(单表一方)的主键约束
其中外键约束是 主表的表名_id 。
sql语句:
-- 用户表
CREATE TABLE `user`(
`uid`INT PRIMARY KEY,
`username` VARCHAR(20) NOT NULL UNIQUE
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 插入数据
insert into `user` (`uid`, `username`) values('3','张三');
insert into `user` (`uid`, `username`) values('4','李四');
insert into `user` (`uid`, `username`) values('5','王五');
insert into `user` (`uid`, `username`) values('6','赵六');
用户表与订单表示一对多关系直接套公式:从表(多表一方)添加外键约束,引用主表(单表一方)的主键约束
其中外键约束是 主表的表名_id 。
ALTER TABLE `orders` ADD FOREIGN KEY(`user_id`) REFERENCES `user`(`uid`);
-- 订单表
CREATE TABLE `orders`(
`oid` INT PRIMARY KEY,
`totalprice` DOUBLE,
`user_id` INT
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 插入数据
insert into `orders` (`oid`, `totalprice`, `user_id`) values('1','1000','3');
insert into `orders` (`oid`, `totalprice`, `user_id`) values('2','800','3');
insert into `orders` (`oid`, `totalprice`, `user_id`) values('3','1250','4');
insert into `orders` (`oid`, `totalprice`, `user_id`) values('4',NULL,'5');
insert into `orders` (`oid`, `totalprice`, `user_id`) values('5',NULL,NULL);
因为多对多表查询不好建立联系,所以引用中间表。可以看成两个一对多表
ALTER TABLE `middle` ADD FOREIGN KEY(`orders_id`) REFERENCES `orders`(`oid`);
ALTER TABLE `middle` ADD FOREIGN KEY(`product_id`)REFERENCES `product`(`pid`);
-- 中间表
CREATE TABLE `middle`(
`orders_id` INT,
`product_id`INT
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 插入数据
insert into `middle` (`orders_id`, `product_id`) values('1','1');
insert into `middle` (`orders_id`, `product_id`) values('1','2');
insert into `middle` (`orders_id`, `product_id`) values('2','2');
insert into `middle` (`orders_id`, `product_id`) values('2','3');
insert into `middle` (`orders_id`, `product_id`) values('3','1');
insert into `middle` (`orders_id`, `product_id`) values('3','2');
insert into `middle` (`orders_id`, `product_id`) values('3','4');
-- 商品表
CREATE TABLE `product`(
`pid` INT PRIMARY KEY,
`pname` VARCHAR(10) NOT NULL UNIQUE,
`price` DOUBLE
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 插入数据
insert into `product` (`pid`, `pname`, `price`) values('1','电视机','600');
insert into `product` (`pid`, `pname`, `price`) values('2','电风扇','400');
insert into `product` (`pid`, `pname`, `price`) values('3','衣柜','400');
insert into `product` (`pid`, `pname`, `price`) values('4','吹风机','250');
这样表与表之间就建立了联系方便查询,通过sqlyog软件,也可以看出来他们之间的联系
1.1内连接
-
隐式内连接
常用的条件查询语句就是隐式内连接如:
select * from
user
where id = 1’ -
显示内连接
语法: 表名 INNER JOIN 表名 ON 条件
-
需求:查询出每个用户所购买商品的订单信息
-- 隐式内连接
-- 添加条件查询 用户表与订单表之间的关系 u.`uid`=o.`user_id`;
SELECT u.*,o.* FROM `user` AS u,`orders` AS o WHERE u.`uid`=o.`user_id`;
-- 采用起别名的方式 可以减少代码
-- 这条语句等同于以上语句
SELECT`user`.`uid`,`user`.`username`,`orders`.`oid`,`orders`.`totalprice`,`orders`.`user_id` FROM `user` ,`orders` WHERE `user`.`uid`=`orders`.`user_id`;
-- 显示内连接
SELECT u.*,o.* FROM `user` AS u INNER JOIN `orders` AS o ON u.`uid`=o.`user_id`;
1.2外连接
-
左外连接
语法:表名 LEFT OUTER JOIN 表名 ON 条件
-
右外连接
语法:表名 RIGHT OUTER JOIN 表名 ON 条件
-
需求:查询出每个用户所购买商品的订单信息
-- 左外连接
SELECT `user`.*,`orders`.* FROM `user` LEFT OUTER JOIN `orders` ON `user`.`uid` = `orders`.`user_id`;
-- left左边的数据都会展示出来,如果用户表中某个人没有下单也能查询出来这个人是谁
SELECT `orders`.*,`user`.* FROM `orders` LEFT OUTER JOIN `user` ON `orders`.`user_id` = `user`.`uid`;
-- 右外连接
SELECT `user`.*,`orders`.* FROM `user` RIGHT OUTER JOIN `orders` ON `user`.`uid` = `orders`.`user_id`;
-- right右边的表数据都会展示出来
SELECT `orders`.*,`user`.* FROM `orders` RIGHT OUTER JOIN `user` ON `orders`.`user_id` = `user`.`uid`;
1.3子查询
子查询:相当于分布查询,第一次查询的结果可以看成一张临时表也可以也看成一个第二次查询时where的条件
- 需求:查看用户为张三的订单详情
-- 显示内连接 隐式内连接 左外连接 右外连接 都能查询 (不过外连接的特点就是会将其他用户的用户信息也查询出来,这点不太好,可以根据不同需求判断用什么连接)
SELECT `user`.*,`orders`.* FROM `user` INNER JOIN `orders` ON `user`.`uid` = `orders`.`user_id` AND `user`.`username`='张三';
-- 单表查询方法
-- 第一步查询张三的id
SELECT `user`.`uid` FROM `user` WHERE `user`.`username` = '张三';
-- 第二步 建立关系:张三的id和订单表的user_id 一致
SELECT `orders`.* FROM `orders` WHERE `orders`.`user_id` = 3; -- 这样查询出来看不见张三的信息了,但是我想让张三的用户表信息也展现出来除了以上几种方式还可以用子查询完成
-- 子查询 把上面两步合二为一
SELECT `orders`.* FROM `orders` WHERE `orders`.`user_id` = (SELECT `user`.`uid` FROM `user` WHERE `user`.`username` = '张三');
-- 利用子查询拼接上用户表中张三的信息
SELECT `user`.*, lsb.* FROM `user`,(SELECT `orders`.* FROM `orders` WHERE `orders`.`user_id` = (SELECT `user`.`uid` FROM `user` WHERE `user`.`username` = '张三'))
AS lsb WHERE lsb.`user_id`=`user`.`uid`; -- 很显然用子查询不方便 技巧:将上一步中查询出来的用户张三的订单看成一张表然后起别名
-
查询所有用户的所有订单以及订单中的商品信息
-- 子查询 -- 第一步由于订单表和商品表是多对多关系 所以引入一个中间表 -- 根据中间表和订单表、商品表示一对多关系所以可以查询出这两个表 SELECT o.*,p.* FROM `orders` AS o,`middle` AS m,`product` AS p WHERE m.`orders_id`=o.`oid` AND m.`product_id`=p.`pid`; -- 第二步把查询出来的表看出临时表 拼接用户表就可以了 SELECT u.*,lsb.* FROM `user` AS u INNER JOIN (SELECT o.*,p.* FROM `orders` AS o,`middle` AS m,`product` AS p WHERE m.`orders_id`=o.`oid` AND m.`product_id`=p.`pid` ) AS lsb ON u.`uid` = lsb.`user_id`; -- 内连接 SELECT u.*,o.*,m.*,p.* FROM `user` AS u,`orders` AS o,`middle` AS m,`product` AS p WHERE u.`uid`=o.`user_id` AND o.`oid`=m.`orders_id` AND m.`product_id`=p.`pid`;
1.4 自查询
自查询:就是把一张表通过起别名区分根据不同需求来查询
- 案列:员工号7369 的 SMITH 他对应的老板编号是(MGR) 7902 而7902 又是员工FORD(7902) 那FORD 对应的老板编号又是 7566所以说 一个员工既是某几个员工的老板,他也有自己的老板,所以我要查询这个员工的所对应的老板 就可以使用自连接查询
sql语句
CREATE TABLE emp(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm DECIMAL(7,2),
deptno INT
) ;
INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp VALUES(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp VALUES(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp VALUES(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp VALUES(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp VALUES(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp VALUES(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp VALUES(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp VALUES(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp VALUES(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp VALUES(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp VALUES(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp VALUES(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
- 需求:我要查询emp表中 员工姓名 所对应的 上司姓名
-- 自查询
SELECT a.`ename`,a.`empno`,b.`ename`,b.`empno` FROM `emp` AS a,`emp` AS b WHERE a.`empno`=b.`mgr`;