zoukankan      html  css  js  c++  java
  • 多表连接及子查询

    本节要点:

    •   连接查询
      • l  笛卡尔连接
      • l  内连接
      • l  外连接
    •   子查询
      • l  单行子查询
      • l  多行子查询

    数据查询语句是最常用也是最复杂的语句,在介绍查询语句之前,我们先定义三个表,以供示例使用:

    •  供应商表(t_supplier):

    存储供应商编号( f_sid),名称(f_sname)和产地(f_city) 的表。

    •   零件表(t_part):

    存储零件的编号(f_pid)名(f_pname)和价格(f_price) 的表。

    •   销售表(t_sells):

    存储关于某个供应商(f_sid)销售的零件(f_pid)的信息。它是联 接其他两个表的结点。

    现有数据:

    t_supplier

    f_sid

    f_sname

    f_city

    1

    Smith

    London

    2

    Jones

    Paris

    3

    Adams

    Rome

    4

    Blake

    Peking

    5

    Zyx

    Jinan

    t_part:

    f_pid

    f_pname

    f_price

    1

    Screw

    10

    2

    Nut

    8

    3

    Bolt

    15

    4

    Gear

    25

    5

    Ball

    5

    t_sells:

    f_id

    f_date

    f_sid

    f_pid

    f_count

    1

    2006-01-01

    1

    1

    10

    2

    2006-01-02

    1

    2

    15

    3

    2006-01-03

    2

    4

    5

    4

    2006-01-04

    3

    1

    100

    5

    2006-01-05

    3

    3

    50

    6

    2006-01-06

    4

    2

    23

    7

    2006-01-07

    4

    3

    78

    8

    2006-01-08

    4

    4

    110

    1         连接查询

    1.1         笛卡尔连接

    查找每个供应商可能供应零件情况 :

    SELECT f_sid,f_pid  FROM  t_supplier,t_part;

    这是查询所有可能的情况,但是这么做意义不大。

    1.2         内连接

    “内连接”或“简单连接”,它会把两个或多个表通过公共列进行连接,只能查询出匹配的记录,不匹配的记录将无法查询出来。公共列是两个或更多表中存在相同数据的列,比如, t_supplier表和t_sells表都包含一个f_sid的公共列。内连接中最常用的就是等值连接和不等值连接。

    1)              等值连接

    连接条件中使用“=”(或者使用关键字inner join)连接两个条件列表 。

    例:查询每个供应商编号,姓名,供应零件编号,零件名称, 零件数量。

    select  s.f_sid, s.f_sname, p.f_pid, p.f_pname,sell.f_count

      from t_supplier s , t_sells sell, t_part p

     where s.f_sid = sell.f_sid

    and sell.f_pid = p.f_pid

    等价于

    select s.f_sid, s.f_sname, p.f_pid, p.f_pname,sell.f_count

      from (t_supplier s inner join t_sells sell on s.f_sid = sell.f_sid ) inner join  t_part p on sell.f_pid = p.f_pid

    2)              不等值连接

    不等值连接就是指连接条件中使用“>”、“>=”、“<=”、“<”、“!=”、“<>”、“BETWEEN…AND…”、“IN”等连接两个条件列表,但是这种方式通常需要和其他等值运算一起使用。

    例:查询供应商售出数量超过10的零件编号和名称

    select p.f_pid, p.f_pname

      from t_supplier s, t_part p, t_sells sell

     where s.f_sid = sell.f_sid

       and sell.f_pid = p.f_pid

       and sell.count>10

    1.3         外连接

    外部连接类型:

    • l  左外连接:  LEFT [OUTER] JOIN
    • l  右外连接:  RIGHT [OUTER] JOIN
    • l  全外连接:  FULL [OUTER] JOIN

    1)         左外连接-left join

    使用左外连接的查询,返回的结果不仅仅是符合连接条件的行记录,还包含了左边表的全部记录。也就是说,如果左表的某行记录在右边表中没有匹配项,则在返回结果中右表的所有选择列表列均为空。

    统计所有供应商各自的销售记录 :

    select t_supplier.f_sid,f_pid,f_id,f_count

    from t_supplier left join t_sells on t_supplier.f_sid=t_sells.f_sid;

    2)         右外联接-rightjoin

    使用右外连接的查询,返回的结果不仅仅是符合连接条件的行记录,还包含了右边表的全部记录。也就是说,如果右表的某行记录在左边表中没有匹配项,则在返回结果中左表的所有选择列表列均为空。

    对于上面的例子,同样我们用RIGHT [OUTER] JOIN可以写成下面的语句:

    select t_supplier.f_sid,f_pid,f_id,f_count

    from t_sells right join t_supplier on t_sells.f_sid=t_supplier.f_sid;

    3)         全外联接-fulljoin

    返回所有匹配成功的记录,并返回左表未匹配成功的记录,也返回右表未成功匹配的记录。注:使用较少。

    我们可以简单的理解为:FULL [OUTER] JOIN 相当于LEFT [OUTER] JOIN和RIGHT [OUTER] JOIN查询的结果集再通过UNION(不是UNION ALL)连接在一起。

    2         子查询

    子查询就是嵌套查询,它是嵌套在另一个语句中的select语句。 可分为下面几类:

    子查询

    说明

    单行子查询

    将包含一列的一行结果返回到外部查询

    多行子查询

    将多行结果返回到外部查询

    相关(关联)子查询

    引用外部查询中的一列,对外部查询中的每一行执行一次子查询

    不相关(非关联)子查询

    首先执行子查询,然后将值传递给外部查询

    规则:

    • l  子查询必须“自身就是一个完整的查询”——也就是说至少包括一个SELECT子句和一个FROM子句
    • l  子查询不能包括ORDER BY子句。如果显示输出需要按照特定顺序显示,那么ORDER BY子句应该作为外部查询的最后一个子句列出
    • l  子查询“必须包括在一组括号中”,以便将它与外部查询分开。
    • l  如果将子查询在外部查询的WHERE或HAVING子句中,那么该子句一般位于比较运算符的“右边”。

    2.1       单行子查询

    当我们需要一个中间结果集/值时,我们就需要使用子查询。返回单值的子查询通常用在WHERE和HAVING子句里

    统计出所有比名为 'Screw' 的零件贵的零件

    select * from t_part

    where f_price>(select f_price from t_part where f_pname='Screw');

    注意:对于本例而言,子查询仅执行一次,因为它不依赖于外层查询。

    2.2       多行子查询

    • l  向父查询返回多行结果的嵌套查询
    • l  最常用在WHERE和HAVING子句中
    • l  包括IN,ALL和ANY运算符

    1)         IN运算符示例:在books表中查询每一个种类中最贵的图书的价格

    SELECT isbn,bretail,bcategory

    FROM books

    WHERE bretail IN

    (SELECT MAX(bretail) FROM books GROUP BY bcategory)

    ORDER BY bcategory;

    • l  子查询确定每一个种类中最贵的图书的价格。
    • l  将每一种类中的最高零售价格传递给外部查询的WHERE子句。
    • l  外部查询将每一本书的价格与子查询生成的价格进行比较。
    • l  如果一本书的零售价与子查询返回的其中一个价格相同,则在查询的输出中显示这本书的书名,零售价 ,种类。

    2)         EXISTS子查询:形式为where [not] exists (子查询)

    统计哪些不销售任何零件的供应商 (比如说,我们想把这些供应商从数据库中删除)

    select * from t_supplier

    where not exists

     (select * from t_sells where t_sells.f_sid=t_supplier.f_sid);

    注意:对于本例而言,我们在WHERE子句的内层SELECT里使用了来自外层SELECT的t_supplier.f_sid。 正如前面所说的,子查询为每个外层查询计算一次,也就是说,t_sells.f_sid的值总是从外层SELECT的实际记录中(t_supplier.f_sid)取得的。

    3)         [NOT] IN子查询:形式为where fieldname [not] in (子查询)

    这种情况适用于子查询中返回多个值时的情况 。

    同上例,统计哪些不销售任何零件的供应商,我们也可以用IN子查询

    select * from t_supplier

    where f_id not in

     (select distinct f_id from t_sells);

    另一个例子:查询出所在城市为Lindon、Rome和Jinan的供应商的名称

    select f_sname from t_supplier where f_city in  (‘Lindon’,’Rome’,’Jinan’);

    4)         ALL和ANY运算符

    运算符

    说明

    >ALL

    大于子查询返回的最大值

    <ALL

    小于子查询返回的最小值

    <ANY

    小于子查询返回的最大值

    >ANY

    大于子查询返回的最小值

    =ANY

    等于子查询返回的任何值(于IN相同)

    示例:查找零售价超过cooking种类最贵的图书(>ALL)

    SELECT title,retail

    FROM books

    WHERE retail>ALL

    (SELECT retail FROM books WHERE category = 'COOKING');

    示例:查找价格低于cooking种类的中最便宜的图书(<ALL)

    SELECT title,retail

    FROM books

    WHERE retail<ALL

    (SELECT retail FROM books WHERE category ='COOKING');

    示例:<ANY,查找其值小于子查询返回的最大值的记录,确定哪些书的售价比cooking种类中最贵的图书更低

    SELECT title,retail

    FROM books

    WHERE retail<ANY

    (SELECT retail FROM books WHERE category ='COOKING');

    示例:>ANY,返回其值大于子查询中返回的最小值的记录

    SELECT title,retail

    FROM books

    WHERE retail>ANY

    (SELECT retail FROM books WHERE category ='COOKING');

    5)         FROM里面的子查询

    当子查询返回一个结果集时,那么它就相当于一个普通的表,因此,在FROM子句我们同样可以使用子查询。这个特性很有用,FROM里的子查询还可以让我们获得多于一个回合的分组/聚集特性,而不需要求助于临时表。这种嵌套可以使用多次,大大提高了查询的功能。

    查询出所有供应商中的最大的销售量:

    select max(product_count) as avgPrice

    from (select sum(f_count) as product_count

             from t_sells

             group by f_sid) subtable;

  • 相关阅读:
    Python 基础(二)
    Python 入门
    DNS
    PXE自动化安装CentOS7和CentOS6
    AIDE及sudo应用
    SSH应用
    KickStart自动化安装Linux
    初见鸟哥
    数组ARRAY
    SSH用法
  • 原文地址:https://www.cnblogs.com/zhouyeqin/p/7299916.html
Copyright © 2011-2022 走看看