目录(?)[+]

  1. 子查询定义
  2. 子查询分类
  1.     21 按返回结果集分类
  2.     22 按照对返回结果的调用方法
  1. 使用子查询原则
  2. 实例分析
  1.     41 创建测试表
  2.     42 插入测试数据
  3.     43 表子查询实例
  4.     44 行子查询实例
  5.     45 标量子查询实例
  6.     46 列子查询实例
  7.     47 where型子查询
  8.     48 from型子查询
  9.     49 exists型子查询



1 子查询定义

    在一个表表达中可以调用另一个表表达式,这个被调用的表表达式叫做子查询(subquery),我么也称作子选择(subselect)或内嵌选择(inner select)。子查询的结果传递给调用它的表表达式继续处理。


2 子查询分类

    2.1 按返回结果集分类

        子查询按返回结果集的不同分为4种:表子查询,行子查询,列子查询和标量子查询。


       

表子查询:返回的结果集是一个行的集合,N行N列(N>=1)。表子查询经常用于父查询的FROM子句中。


       

行子查询:返回的结果集是一个列的集合,一行N列(N>=1)。行子查询可以用于福查询的FROM子句和WHERE子句中。


       

列子查询:返回的结果集是一个行的集合,N行一列(N>=1)。


        标量子查询:返回的结果集是一个标量集合,一行一列,也就是一个标量值。可以指定一个标量表达式的任何地方,都可以用一个标量子查询。

        从定义上讲,每个标量子查询也是一个行子查询和一个列子查询,反之则不是;每个行子查询和列子查询也是一个表子查询,反之也不是。

    2.2 按照对返回结果的调用方法

        子查询按对返回结果集的调用方法,可分为where型子查询,from型子查询及exists型子查询。


        where型子查询:(把内层查询结果当作外层查询的比较条件)


        定义:where型的子查询就是把内层查询的结果当作外层查询的条件。


        from型子查询:(把内层的查询结果供外层再次查询)


        定义:from子查询就是把子查询的结果(内存里的一张表)当作一张临时表,然后再对它进行处理。


        exists型子查询:(把外层查询结果拿到内层,看内层的查询是否成立)


        定义:exists子查询就是对外层表进行循环,再对内表进行内层查询。和in ()差不多,但是它们还是有区别的。主要是看两个张表大小差的程度。若子查询表大则用exists(内层索引),子查询表小则用in(外层索引);


3 使用子查询原则

    1.一个子查询必须放在圆括号中。


    2.将子查询放在比较条件的右边以增加可读性。


    子查询不包含 ORDER BY 子句。对一个 SELECT 语句只能用一个 ORDER BY 子句,并且如果指定了它就必须放在主 SELECT 语句的最后。


    3.在子查询中可以使用两种比较条件:单行运算符(>, =, >=, <, <>, <=) 和多行运算符(IN, ANY, ALL)。


4 实例分析

    4.1 创建测试表



[sql]


1. CREATE TABLE
2. INTEGER      NOT NULL,  
3. NAME           CHAR(15)     NOT NULL,  
4. CHAR(3)      NOT NULL,  
5. DATE
6. CHAR(1)      NOT NULL,  
7. SMALLINT     NOT NULL,  
8. VARCHAR(30)  NOT NULL,  
9. CHAR(4)              ,  
10. CHAR(6)              ,  
11. VARCHAR(30)  NOT NULL,  
12. CHAR(13)             ,  
13. CHAR(4)              ,  
14. PRIMARY KEY
15.   
16. CREATE   TABLE
17. INTEGER      NOT NULL,  
18. INTEGER      NOT NULL,  
19. DATE         NOT NULL,  
20. DECIMAL(7,2) NOT NULL,  
21. PRIMARY KEY



CREATE TABLE PLAYERS
    (PLAYERNO      INTEGER      NOT NULL,
    NAME           CHAR(15)     NOT NULL,
    INITIALS       CHAR(3)      NOT NULL,
    BIRTH_DATE     DATE                 ,
    SEX            CHAR(1)      NOT NULL,
    JOINED         SMALLINT     NOT NULL,
    STREET         VARCHAR(30)  NOT NULL,
    HOUSENO        CHAR(4)              ,
    POSTCODE       CHAR(6)              ,
    TOWN           VARCHAR(30)  NOT NULL,
    PHONENO        CHAR(13)             ,
    LEAGUENO       CHAR(4)              ,
    PRIMARY KEY    (PLAYERNO));

CREATE   TABLE PENALTIES
        (PAYMENTNO      INTEGER      NOT NULL,
         PLAYERNO       INTEGER      NOT NULL,
         PAYMENT_DATE   DATE         NOT NULL,
         AMOUNT         DECIMAL(7,2) NOT NULL,
         PRIMARY KEY    (PAYMENTNO));

    注:表players为球员信息基本表,表penalties为有过罚款记录的球员信息列表。

    4.2 插入测试数据



[sql]

1. INSERT INTO PLAYERS VALUES (2, ‘Everett’, ‘R’, ‘1948-09-01’, ‘M’, 1975, ‘Stoney Road’,‘43’, ‘3575NH’, ‘Stratford’, ‘070-237893’, ‘2411’);  
2. INSERT INTO PLAYERS VALUES (6, ‘Parmenter’, ‘R’, ‘1964-06-25’, ‘M’, 1977, ‘Haseltine Lane’,‘80’, ‘1234KK’, ‘Stratford’, ‘070-476537’, ‘8467’);  
3. INSERT INTO PLAYERS VALUES (7, ‘Wise’, ‘GWS’, ‘1963-05-11’, ‘M’, 1981, ‘Edgecombe Way’,‘39’, ‘9758VB’, ‘Stratford’, ‘070-347689’, NULL);  
4. INSERT INTO PLAYERS VALUES (8, ‘Newcastle’, ‘B’, ‘1962-07-08’, ‘F’, 1980, ‘Station Road’,‘4’, ‘6584WO’, ‘Inglewood’, ‘070-458458’, ‘2983’);  
5. INSERT INTO PLAYERS VALUES (27, ‘Collins’, ‘DD’, ‘1964-12-28’, ‘F’, 1983, ‘Long Drive’,‘804’, ‘8457DK’, ‘Eltham’, ‘079-234857’, ‘2513’);  
6. INSERT INTO PLAYERS VALUES (28, ‘Collins’, ‘C’, ‘1963-06-22’, ‘F’, 1983, ‘Old Main Road’,‘10’, ‘1294QK’, ‘Midhurst’, ‘010-659599’, NULL);  
7. INSERT INTO PLAYERS VALUES (39, ‘Bishop’, ‘D’, ‘1956-10-29’, ‘M’, 1980, ‘Eaton Square’,‘78’, ‘9629CD’, ‘Stratford’, ‘070-393435’, NULL);  
8. INSERT INTO PLAYERS VALUES (44, ‘Baker’, ‘E’, ‘1963-01-09’, ‘M’, 1980, ‘Lewis Street’,‘23’, ‘4444LJ’, ‘Inglewood’, ‘070-368753’, ‘1124’);  
9. INSERT INTO PLAYERS VALUES (57, ‘Brown’, ‘M’, ‘1971-08-17’, ‘M’, 1985, ‘Edgecombe Way’,‘16’, ‘4377CB’, ‘Stratford’, ‘070-473458’, ‘6409’);  
10. INSERT INTO PLAYERS VALUES (83, ‘Hope’, ‘PK’, ‘1956-11-11’, ‘M’, 1982, ‘Magdalene Road’,‘16A’, ‘1812UP’, ‘Stratford’, ‘070-353548’, ‘1608’);  
11. INSERT INTO PLAYERS VALUES (95, ‘Miller’, ‘P’, ‘1963-05-14’, ‘M’, 1972, ‘High Street’,‘33A’, ‘5746OP’, ‘Douglas’, ‘070-867564’, NULL);  
12. INSERT INTO PLAYERS VALUES (100, ‘Parmenter’, ‘P’, ‘1963-02-28’, ‘M’, 1979, ‘Haseltine Lane’,‘80’, ‘6494SG’, ‘Stratford’, ‘070-494593’, ‘6524’);  
13. INSERT INTO PLAYERS VALUES (104, ‘Moorman’, ‘D’, ‘1970-05-10’, ‘F’, 1984, ‘Stout Street’,‘65’, ‘9437AO’, ‘Eltham’, ‘079-987571’, ‘7060’);  
14. INSERT INTO PLAYERS VALUES (112, ‘Bailey’, ‘IP’, ‘1963-10-01’, ‘F’, 1984, ‘Vixen Road’,‘8’, ‘6392LK’, ‘Plymouth’, ‘010-548745’, ‘1319’);  
15.   
16. INSERT INTO PENALTIES VALUES (1,  6, ‘1980-12-08’,100);  
17. INSERT INTO PENALTIES VALUES (2, 44, ‘1981-05-05’, 75);  
18. INSERT INTO PENALTIES VALUES (3, 27, ‘1983-09-10’,100);  
19. INSERT INTO PENALTIES VALUES (4,104, ‘1984-12-08’, 50);  
20. INSERT INTO PENALTIES VALUES (5, 44, ‘1980-12-08’, 25);  
21. INSERT INTO PENALTIES VALUES (6,  8, ‘1980-12-08’, 25);  
22. INSERT INTO PENALTIES VALUES (7, 44, ‘1982-12-30’, 30);  
23. INSERT INTO PENALTIES VALUES (8, 27, ‘1984-11-12’, 75);


INSERT INTO PLAYERS VALUES (2, 'Everett', 'R', '1948-09-01', 'M', 1975, 'Stoney Road','43', '3575NH', 'Stratford', '070-237893', '2411');
INSERT INTO PLAYERS VALUES (6, 'Parmenter', 'R', '1964-06-25', 'M', 1977, 'Haseltine Lane','80', '1234KK', 'Stratford', '070-476537', '8467');
INSERT INTO PLAYERS VALUES (7, 'Wise', 'GWS', '1963-05-11', 'M', 1981, 'Edgecombe Way','39', '9758VB', 'Stratford', '070-347689', NULL);
INSERT INTO PLAYERS VALUES (8, 'Newcastle', 'B', '1962-07-08', 'F', 1980, 'Station Road','4', '6584WO', 'Inglewood', '070-458458', '2983');
INSERT INTO PLAYERS VALUES (27, 'Collins', 'DD', '1964-12-28', 'F', 1983, 'Long Drive','804', '8457DK', 'Eltham', '079-234857', '2513');
INSERT INTO PLAYERS VALUES (28, 'Collins', 'C', '1963-06-22', 'F', 1983, 'Old Main Road','10', '1294QK', 'Midhurst', '010-659599', NULL);
INSERT INTO PLAYERS VALUES (39, 'Bishop', 'D', '1956-10-29', 'M', 1980, 'Eaton Square','78', '9629CD', 'Stratford', '070-393435', NULL);
INSERT INTO PLAYERS VALUES (44, 'Baker', 'E', '1963-01-09', 'M', 1980, 'Lewis Street','23', '4444LJ', 'Inglewood', '070-368753', '1124');
INSERT INTO PLAYERS VALUES (57, 'Brown', 'M', '1971-08-17', 'M', 1985, 'Edgecombe Way','16', '4377CB', 'Stratford', '070-473458', '6409');
INSERT INTO PLAYERS VALUES (83, 'Hope', 'PK', '1956-11-11', 'M', 1982, 'Magdalene Road','16A', '1812UP', 'Stratford', '070-353548', '1608');
INSERT INTO PLAYERS VALUES (95, 'Miller', 'P', '1963-05-14', 'M', 1972, 'High Street','33A', '5746OP', 'Douglas', '070-867564', NULL);
INSERT INTO PLAYERS VALUES (100, 'Parmenter', 'P', '1963-02-28', 'M', 1979, 'Haseltine Lane','80', '6494SG', 'Stratford', '070-494593', '6524');
INSERT INTO PLAYERS VALUES (104, 'Moorman', 'D', '1970-05-10', 'F', 1984, 'Stout Street','65', '9437AO', 'Eltham', '079-987571', '7060');
INSERT INTO PLAYERS VALUES (112, 'Bailey', 'IP', '1963-10-01', 'F', 1984, 'Vixen Road','8', '6392LK', 'Plymouth', '010-548745', '1319');

INSERT INTO PENALTIES VALUES (1,  6, '1980-12-08',100);
INSERT INTO PENALTIES VALUES (2, 44, '1981-05-05', 75);
INSERT INTO PENALTIES VALUES (3, 27, '1983-09-10',100);
INSERT INTO PENALTIES VALUES (4,104, '1984-12-08', 50);
INSERT INTO PENALTIES VALUES (5, 44, '1980-12-08', 25);
INSERT INTO PENALTIES VALUES (6,  8, '1980-12-08', 25);
INSERT INTO PENALTIES VALUES (7, 44, '1982-12-30', 30);
INSERT INTO PENALTIES VALUES (8, 27, '1984-11-12', 75);

    如:获取编号小于10的男性球员的号码



[sql]


1. mysql> select playerno from
2. select
3. from
4. where
5. as players10 where sex=‘M’;



mysql> select playerno from (
    select playerno, sex 
    from players 
    where playerno < 10) 
as players10 where sex='M';

mysql 手机号4到7位星号_标量

    4.4 行子查询实例

    如:获取和100号球员性别相同并且居住在同一城市的球员号码。



[sql]

1. mysql> select
2. from
3. where
4. select
5. from
6. where



mysql> select playerno 
from players 
where (sex, town) = (
    select sex, town 
    from players 
    where playerno = 100);

mysql 手机号4到7位星号_标量_02

    说明:子查询的结果是带有两个值的一行:(’M’,’stratford’)。这个值和一个行表达式(sex,town)进行比较。


    4.5 标量子查询实例

    可以指定一个标量表达式的任何地方,几乎都可以使用一个标量子查询。
    如:获取和27号球员出生在同一年的球员的号码



[sql]

1. mysql> select
2. from
3. where year(birth_date) =   
4. select year(birth_date)   
5. from
6. where
7. and



mysql> select playerno 
from players 
where year(birth_date) = 
    (select year(birth_date) 
    from players 
    where playerno = 27) 
and playerno <> 27;

mysql 手机号4到7位星号_mysql_03

    上面语句等同于:



[sql]



  1. mysql> select playerno from players where year(birth_date) = 1964 and



mysql> select playerno from players where year(birth_date) = 1964 and playerno <> 27;

    4.6 列子查询实例

    由于列子查询返回的结果集是 N 行一列,因此不能直接使用 =   >   <   >=   <=   <> 这些比较标量结果的操作符。在列子查询中可以使用 IN、ANY(SOME)和ALL操作符:
    IN:在指定项内,同 IN(项1,项2,…)。
    ANY:与比较操作符联合使用,ANY关键字必须接在一个比较操作符的后面,表示与子查询返回的任何值比较为 TRUE ,则返回 TRUE 。
    SOME:ANY 的别名,较少使用。
    ALL:与比较操作符联合使用,ALL关键字必须接在一个比较操作符的后面,表示与子查询返回的所有值比较都为 TRUE ,则返回 TRUE 。

    实例1(in):获取球员性别为女的所有球员的球员号,名字及所在城市。



[sql]


1. mysql> select playerno, name, town   
2. from
3. where playerno in
4. select
5. from
6. where sex = ‘F’);



mysql> select playerno, name, town 
from players 
where playerno in 
    (select playerno 
    from players 
    where sex = 'F');

mysql 手机号4到7位星号_子查询_04

    实例2(any):获取至少比同城的另一球员年轻的所有球员的号码,日期和居住城市。



[sql]


1. mysql> select
2. from players as
3. where birth_date > any
4. select
5. from players as
6. where



mysql> select playerno, birth_date, town 
from players as p1 
where birth_date > any 
    (select birth_date 
    from players as p2 
    where p1.town = p2.town);



mysql 手机号4到7位星号_mysql_05

    


    实例3(all):获取最老球员的号码,名字及生日。(即出生日期数值小于或等于所有其它球员的球员)



[sql]


    1. mysql> select playerno, name, birth_date   
    2. from
    3. where birth_date <= all
    4. select
    5. from



    mysql> select playerno, name, birth_date 
    from players 
    where birth_date <= all 
        (select birth_date 
        from players);

    mysql 手机号4到7位星号_子查询_06


        4.7 where型子查询

            参考4.4节子查询语句

        4.8 from型子查询

            参考4.3节子查询语句

        4.9 exists型子查询

        EXISTS关键字表示存在。使用EXISTS关键字时,内层查询语句不返回查询的记录,而是返回一个真假值,如果内层查询语句查询到满足条件的记录,只要子查询中至少返回一个值,则EXISTS语句的值就为True。就返回true,否则返回false。当返回的值为true时,外层查询语句将进行查询,否则不进行查询。NOT EXISTS刚好与之相反。exists的用法和in ()差不多,但是它们还是有区别的。主要是看两个张表大小差的程度。若子查询表大则用exists(内层索引),子查询表小则用in(外层索引);

        实例1(exists):获取那些至少支付了一次罚款的球员的名字和首字母。



    [sql]


    1. mysql> select name, initials   
    2. from
    3. where
    4. select * from
    5. where



    mysql> select name, initials 
    from players 
    where exists 
        (select * from penalties 
        where playerno = players.playerno);



    mysql 手机号4到7位星号_mysql_07


        实例2(not exists):获取那些从来没有罚款的球员的名字和首字母。



    [sql]


    1. mysql> select name, initials   
    2. from
    3. where not
    4. select * from
    5. where



    mysql> select name, initials 
    from players 
    where not exists 
        (select * from penalties 
        where playerno = players.playerno);



    mysql 手机号4到7位星号_标量_08