Key word#多表查询(子查询+联结+组合查询)

1.标量子查询
    子查询:嵌套在其他查询中的查询
    标量子查询:只返回一行一列(即一个单元格数据)的子查询,相当于一个常数;也可以当作常数列加在结尾。
    注意:子查询可多层嵌套,不限制嵌套层数,但性能会有影响

2.关联子查询
    嵌套再其他查询中的查询,适用于组内比较。
    子查询返回一列数据:子查询的结果,与主查询的目标列存在一定关联

3.普通子查询
    嵌套再其他查询中的查询。
    子查询返回一列数据:将子查询的结果列,作为主查询的取值范围。(#把in/大于小于这类的范围用select语句代替)
    PS:将二维表作为主查询新的检索表


★★★表联结
    检索数据时必须用联结
    联结:一种机制,关联多个表,返回一组输出,在一条select语句中实现;主键:唯一标识,可以是ID或者其他唯一值(身份证号)
    补充:联接不是物理实体,在实际数据库表中不存在
    联接方式 “=”,有些类似于excel中的 VLOOKUP
    分类:
        1. ★内部联结(INNER JOIN)
            前提-必须有共同列,等值联结
            结果-所有表的所有列、共同列重复的行
            创建联结规则-列出所有表、定义所有表关系
                例如:所有表-pro_info AS p, supplier_info AS s, order_list AS l,那么表关系有
                p.supplier_id=s.supplier_id;p.prod_id=l.prod_id;三张表里两两联结了
                pro_info AS p, supplier_info AS s, order_list AS l中,三个表中的“,”可以用inner join代替,后面如果有where 用on 代替

            相比子查询,性能更好,可以从多个表中选择结果字段

        2. 自联结
            前提-联结表为同一个
            结果-返回所有数据
            创建联结规则-列出所有表、定义所有表关系
                例如:所有表-pro_info AS p1,pro_info AS p2
                    p1.supplier_id = p2.supplier_id;p1.prod_name='原味薯片';p1.brand='乐事';

                注意输出结果字段的选择(注意别名)


        3. ★★外部联接(LEFT OUTER JOIN/ RIGHT OUTER JOIN/ FULL OUTER JOIN)
            前提-必须有共同列
            结果-所有表的所有列、包含相关表中没有关联行的行
            创建联结规则-列出所有表、定义所有表关系
                左外部联结-包含左边表的所有行:LEFT OUTER JOIN
                右外部联结-包含右边表的所有行:RIGHT OUTER JOIN
                全外部联结-包含两边表的所有行:FULL OUTER JOIN

            注意联结语法、联结条件、多表联结时,先分别测试每个联结

        在联结中使用聚合函数
            联结>>嵌套>>聚合>>简化
            先联结得到一个虚拟表;对虚拟表进行二次查询;在虚拟表基础上进行聚合操作;剥除虚拟表,留下作用语句
            示例:SELECT cust_id, cust_name, COUNT(DISTINCT order_id) order_num  FROM( ) a  GROUP BY cust_id;


    组合查询—UNION
        多条select语句:UNION + SELECT + 列字段 + FROM +单个/多个表 + 'order by'
        要求:自动过滤重复行+两条及两条以上的select语句;每两条之间union一次;union all关键字
        列字段要求:相同的列、表达式或者聚集函数;数据类型必须兼容(允许隐式转换);最终字段名由第一条SELECT语句决定
        ORDER BY:最后一条SELECT 语句中,作用整个检索结果

关于代码:

-- 多表查询
SELECT * from milk_tea as m;

SELECT m.sale_price FROM milk_tea as m WHERE m.prod_name = '方便面';

SELECT * 
From milk_tea as m1 
WHERE m1.sale_price > (
	                  SELECT m.sale_price 
					  FROM milk_tea as m 
			          WHERE m.prod_name = '方便面');

SELECT m1.* ,
					(SELECT m.sale_price 
					FROM milk_tea AS m 
					WHERE m.prod_name = '奶茶')
FROM milk_tea AS m1;

SELECT * 
FROM prod_info as p;

SELECT p.class,avg(p.sale_price) 
FROM prod_info as p 
group by p.class
HAVING avg(p.sale_price)>(SELECT m.sale_price 
						FROM milk_tea AS m 
				WHERE m.prod_name = '奶茶');

-- 3个标量子查询并在一起
SELECT *
FROM prod_info as p2
where  p2.sale_price >(SELECT avg(p.sale_price) 
					FROM prod_info as p
					WHERE p.class = p2.class
					group by p.class);

-- 继续子查询
SELECT m.prod_name FROM milk_tea AS m WHERE m.sale_price = 15;
SELECT * FROM milk_tea as m where m.prod_name in ('奶茶','薯片','薯条');

-- 注意区分好m1与m2
SELECT * 
FROM milk_tea as m1 
where m1.prod_name in (
						SELECT m2.prod_name 
						FROM milk_tea AS m2 
						WHERE m2.sale_price = 15);

SELECTlect * from prod_info;

SELECT p.prod_name,p.type,p.sale_price FROM prod_info as p WHERE prod_name = '抽纸';
SELECT a.type FROM (SELECT p.prod_name,p.type,p.sale_price FROM prod_info as p WHERE prod_name = '抽纸') as a WHERE a.sale_price > 26; 

-- 联接
SELECT * FROM prod_info;
SELECT * FROM supplier_info;

SELECT p.*,s.* 
FROM prod_info AS p,supplier_info as S
WHERE p.supplier_id = s.supplier_id;

SELECT * FROM order_list;
SELECT * from prod_info;

SELECT l.prod_id FROM order_list AS l WHERE l.order_id = '20190403001';

SELECT * FROM prod_info AS P WHERE p.prod_id IN (SELECT l.prod_id FROM order_list AS l WHERE l.order_id = '20190403001');

-- 内部联结
SELECT p.*, l.*
FROM prod_info AS p, order_list AS l
WHERE p.prod_id = l.prod_id
 AND l.order_id = '20190403001';

-- 改联结查询
SELECT p.*, l.*
FROM prod_info AS p INNER JOIN order_list AS l
ON p.prod_id = l.prod_id
 AND l.order_id = '20190403001';

SELECT * FROM cust_info AS c;
SELECT * FROM order_list AS l;
-- 假设要查19年4月7日购买情况
SELECT * FROM order_list AS l WHERE l.order_id LIKE '20190407%';
-- 假设要查当天购买+客户信息
SELECT c.*,l.* 
FROM cust_info AS c LEFT OUTER JOIN order_list AS l 
ON c.cust_id = l.cust_id
AND l.order_id LIKE '20190401%';
-- 结果保留了所有客户信息,但是0401没有购买商品的客户,数据表没有保存

-- 查看每个客户购买了多少商品
SELECT c2.cust_id, COUNT(c2.prod_id)
FROM(SELECT c.cust_id, c.cust_name, l.prod_id, l.prodname, l.order_id
		FROM cust_info AS c LEFT OUTER JOIN order_list AS l 
		ON c.cust_id = l.cust_id
		AND l.order_id LIKE '20190401%') AS c2
GROUP BY c2.cust_id;

-- 直接对联结进行聚合,把FROM后面的部分当成结果表,整体再进行分组聚合

SELECT c.cust_id, COUNT(l.prod_id)
FROM cust_info AS c LEFT OUTER JOIN order_list AS l 
ON c.cust_id = l.cust_id
AND l.order_id LIKE '20190401%'
GROUP BY c.cust_id;

-- UNION写法
SELECT * FROM order_list AS l WHERE l.order_id LIKE '20190407%'
UNION ALL(区分UNION 和 UNION ALL)
SELECT * FROM order_list AS l WHERE l.order_id LIKE '20190407%';

– 习题补充
/* 多表查询例题,用产品信息表与流水表查询
1、找出所有洁云牌抽纸的销售流水(使用标量子查询)。
2、找出各类商品中,价格高于该类商品均价的部分(使用关联子查询)。
3、用联结的方法改写第一题。
4、归总下所有商品的销量。
*/

SELECT * FROM prod_info;
SELECT * FROM order_list;

– 标量子查询 找出所有洁云牌抽纸的销售流水

SELECT * 
FROM order_list as l 
WHERE l.prod_id = (
						SELECT p.prod_id 
						FROM prod_info as p 
						WHERE p.prod_name = '抽纸' 
						and p.brand = '洁柔') ;

– 关联子查询:找出各类商品中,价格高于该类商品均价的部分(使用关联子查询)

SELECT * 
FROM prod_info as p1
WHERE p1.sale_price >(
							SELECT AVG(sale_price) 
							FROM prod_info as p2 
							WHERE p2.class = p1.class 
							GROUP BY p1.class);

– 用联结的方式改写第一题

SELECT * 
FROM order_list as l INNER JOIN prod_info as p
ON p.prod_name = '抽纸' and p.brand = '洁柔' 
and p.prod_id = l.prod_id;

– 归总下所有商品的销量

SELECT p.prod_name, p.brand, SUM(l.quantity) as Quantity 
FROM prod_info as p LEFT OUTER JOIN order_list as l
ON p.prod_id = l.prod_id 
GROUP BY p.prod_name, p.brand;