MySQL入门(11)——基于datagrip的表关联查询及视图

目录

  • 一、表关联查询
    • 1、表别名
    • 2、内连接
      • (1)两表内联
      • (2)笛卡尔积
      • (3)多表内联
    • 3、外连接
      • (1)左外连接
      • (2)右外连接
    • 4、自连接
  • 二、视图
    • 1、视图作用
    • 2、创建视图

所用到的数据看之前文章,已提供,下面跟着操作即可

一、表关联查询

1、表别名

当表的名字很长或者执行一些特殊查询时,为了方便操作或者需要多次使用相同的表时,可以为表指定别名,以替代表原来的名称。

在为表取别名时,要保证不能与数据库中的其他表的名称冲突。

对单表做简单的别名查询通常是无意义的。一般是对一个表要当作多个表来操作,或者是对多个表进行操作时,才设置表别名。

当为表取别名后,列名前面最好都加上表的别名,做以区分。

 SELECT p.*,v.vend_name 
 FROM products p ,vendors v  
 WHERE p.vend_id=v.vend_id;

使用表别名查询,可以使 SQL 变得简洁而更易书写和阅读,尤其在 SQL 比较复杂的情况下。除了使用别名来简化 SQL 外,有些时候例如一个表做自身关联时,必须要使用别名来当作两个表进行关联操作。

2、内连接

MySQL入门(11)——基于datagrip的表关联查询及视图_第1张图片

(1)两表内联

案例:假设现在想查询给供货的供应商的名称,以及商品名称和商品价格。此时发现,要查询的字段不在同一张表里。供应商名称在vendors表里,而商品名称和商品价格在products表里,这时可以使用内联查询,将两张表进行关联之后进行查询。

# 这里没有使用表别名
 SELECT vend_name, prod_name, prod_price
 FROM products,
      vendors
 WHERE vendors.vend_id = products.vend_id;
 
 # 这种方式叫等值连接。也可以用表别名,来达到同样效果
 SELECT v.vend_name, p.prod_name, p.prod_price
 FROM products p,  # 起了别名就要用
      vendors v
 WHERE p.vend_id = v.vend_id;
 
 # 这种连接方式也被称为内部连接,可以用以下语法来明确指定连接类型 
 SELECT vend_name, prod_name, prod_price
 FROM products  INNER JOIN vendors         #内连接的关键字inner join,inner可以省略
 ON vendors.vend_id = products.vend_id;  
 
 # 这两种方式都叫内连接,一种是隐式内联,一种是显示内联 

练习:编写SQL语句,返回customers表中的顾客名称cust_name 和orders表中的相关订单号order_num,并按顾客名称再按订单号对结果进行排序。

# 等值连接查询:
SELECT cust_name,order_num 
FROM customers ,orders 
WHERE customers.cust_id=orders.cust_id;

# inner join 语法查询:
SELECT cust_name,order_num 
FROM customers  INNER JOIN orders 
ON customers.cust_id=orders.cust_id;

(2)笛卡尔积

在数据库表的定义中不存在能指示MySQL如何对表进行联结的东西。
必须自己通过SQL做这件事情。

在联结两个表时,实际上做的是将第一个表中的每一行与第二个表中的每一行配对。
WHERE子句作为过滤条件,它只包含那些匹配给定条件(这里是联结条件)的行。
没有WHERE子句,第一个表中的每个行将与第二个表中的每个行配对,而不管它们逻辑上是否可以配在一起。

笛卡儿积(cartesian product) 由没有联结条件的表关系返回的结果为笛卡儿积。
检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。

 SELECT v.vend_name, p.prod_name, p.prod_price
 FROM products p,  vendors v ORDER BY vend_name,prod_name;

从上面的输出中可以看到,相应的笛卡儿积不是我们所想要的。这里返回的数据用每个供应商匹配了每个产品,它包括了供应商不正确的产品。实际上有的供应商根本就没有产品。所以两表联查时,一定要注意where条件。

(3)多表内联

SQL对一条SELECT语句中可以联结的表的数目没有限制。创建联结的基本规则也相同。

案例:假设现在要查询订单编号为20005的产品名称,产品价格、产品数量、供应商名称。该如何查询呢?

首先,先确认要查询的字段来自哪几张表,经分析可以得出,可从orderitems、products、venders中获取数据
其次,再确定三张表的关联关系
然后,确定过滤条件

 -- 隐式连接
 SELECT prod_name, vend_name, prod_price, quantity
 FROM vendors,
      products,
      orderitems
 WHERE vendors.vend_id = products.vend_id
   AND products.prod_id = orderitems.prod_id
   AND order_num = 20005;
   
 -- 显示连接
 SELECT prod_name, vend_name, prod_price, quantity
 FROM orderitems o
          JOIN products p ON o.prod_id = p.prod_id
          JOIN vendors v ON p.vend_id = v.vend_id
 WHERE o.order_num = 20005;

3、外连接

在使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包括其所有行的表。
RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表。

(1)左外连接

 # 查询所有客户的订单情况,包括没有订单的客户
 SELECT customers.cust_id, orders.order_num
 FROM customers
          LEFT OUTER JOIN orders ON customers.cust_id = orders.cust_id;    # OUTER 可以省略

(2)右外连接

上面的例子使用LEFT OUTER JOIN从FROM子句的左边表(customers表)中选择所有行。
为了从右边的表中选择所有行,应该使用RIGHT OUTER JOIN,如下例所示:

 SELECT customers.cust_id, orders.order_num
 FROM customers
          RIGHT OUTER JOIN orders ON customers.cust_id = orders.cust_id;

4、自连接

案例:假设发现商品id为60001的商品存在质量缺陷,现在需要查找,60001供应商所提供的所有商品的名称和商品id

分析过程:

 # 1.使用现有的知识储备,子查询
 # 方法一:
 SELECT vend_id FROM products WHERE prod_id=60001;
 SELECT prod_id,prod_name FROM products WHERE vend_id=1001;
 # 方法二:
 SELECT prod_id,prod_name FROM products 
 WHERE vend_id=(SELECT vend_id FROM products WHERE prod_id=60001);
 
 # 2.采用自连接
 SELECT p1.prod_id, p1.prod_name, p1.vend_id
 FROM products p1,
      products p2
 WHERE p1.vend_id = p2.vend_id
   AND p2.prod_id = 60001;

练习:
1、使用innor join 编写SQL,查询每个顾客的名称,和所有订单号;

 SELECT cust_name,order_num 
 FROM customers INNER JOIN orders 
 ON customers.cust_id=orders.cust_id; 

2、修改上一题的SQL语句,列出所有顾客,即使他们没有下过订单

 SELECT cust_name,order_num 
 FROM customers LEFT JOIN orders 
 ON customers.cust_id=orders.cust_id;

3、使用outer join 连接products表和orderitems表,返回产品名称prod_name 和与之相关的订单号order_num的列表,并按商品名称排序。

SELECT prod_name,order_num 
FROM products LEFT JOIN orderitems 
ON products.prod_id = orderitems.prod_id `在这里插入代码片`
ORDER BY prod_name;

4、修改上一题中创建的SQL语句,使其返回每一项产品的总订单数(不是订单号)。

 SELECT prod_name, COUNT(order_num) AS orders
 FROM products LEFT OUTER JOIN orderitems
 ON products.prod_id = orderitems.prod_id
 GROUP BY prod_name
 ORDER BY prod_name;

5、编写SQL语句,列出供应商id(vend_id)及其可供产品的数量,包括没有产品的供应商。
提示:使用外连接和分组。

 SELECT vendors.vend_id, COUNT(prod_id)
 FROM vendors LEFT OUTER JOIN products 
 ON vendors.vend_id = products.vend_id
 GROUP BY vendors.vend_id;

二、视图

1、视图作用

视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。

查询订购了某个特定订单信息来说,任何需要这个数据的人都必须理解相关表的结构,并且知道如何创建查询和对表进行联结。

 SELECT prod_name, vend_name, prod_price, quantity
 FROM orderitems o
          JOIN products p ON o.prod_id = p.prod_id
          JOIN vendors v ON p.vend_id = v.vend_id
 WHERE o.order_num = 20005;

为了检索其他产品(或多个产品)的相同数据,必须修改最后的WHERE子句。

在视图创建之后,可以用与表基本相同的方式利用它们。可以对视图执行SELECT操作,过滤和排序数据,将视图联结到其他视图或表,甚至能添加和更新数据。

重要的是知道视图仅仅是用来查看存储在别处的数据的一种设施。视图本身不包含数据,因此它们返回的数据是从其他表中检索出来的。在添加或更改这些表中的数据时,视图将返回改变过的数据。

因为视图不包含数据,所以每次使用视图时,都必须处理查询执行时所需的任一个检索。如果你用多个联结和过滤创建了复杂的视图或者嵌套了视图,可能会发现性能下降得很厉害。所以不要滥用视图。

注意事项:
1、与表一样,视图必须唯一命名(不能给视图取与别的视图或表相同的名字)。
2、 对于可以创建的视图数目没有限制。
3、 为了创建视图,必须具有足够的访问权限。这些限制通常由数据库管理人员授予。
4、视图可以嵌套,即可以利用从其他视图中检索数据的查询来构造一个视图。
5、ORDER BY可以用在视图中,但如果从该视图检索数据SELECT中也含有ORDER BY,那么该视图中的ORDER BY将被覆盖。
6、视图不能索引,也不能有关联的触发器或默认值。
7、视图可以和表一起使用。例如,编写一条联结表和视图的SELECT语句。

2、创建视图

在理解什么是视图(以及管理它们的规则及约束)后,来看一下视图的创建。

视图用CREATE VIEW语句来创建。

使用SHOW CREATE VIEW viewname;来查看创建视图的语句。

用DROP删除视图,其语法为DROP VIEW viewname;。

更新视图时,可以先用DROP再用CREATE,也可以直接用CREATE OR REPLACE VIEW。如果要更新的视图不存在,则第2条更新语句会创建一个视图;如果要更新的视图存在,则第2条更新语句会替换原有视图。

(1)查询订单编号为20005的:产品名称,供应商名称,产品价格,购买数量

SELECT order_num,prod_name, vend_name, prod_price, quantity
 FROM orderitems o
          JOIN products p ON o.prod_id = p.prod_id
          JOIN vendors v ON p.vend_id = v.vend_id
 WHERE o.order_num = 20005;

(2)创建视图,包含所有订单的产品名称,供应商名称,产品价格,购买数量

 CREATE VIEW order_detail AS
     SELECT order_num,prod_name, vend_name, prod_price, quantity
 FROM orderitems o
          JOIN products p ON o.prod_id = p.prod_id
          JOIN vendors v ON p.vend_id = v.vend_id;

MySQL入门(11)——基于datagrip的表关联查询及视图_第2张图片

(3)查看视图的所有数据

 SELECT * FROM order_detail;

(4)从视图中过滤数据

SELECT * FROM order_detail WHERE order_num=20005;

(5)删除视图

 DROP VIEW order_detail; 

删完左边栏里的视图就木有了

你可能感兴趣的:(数据库,数据库,mysql,sql,datagrip)