zoukankan      html  css  js  c++  java
  • 6-SQL子查询

    (1) 什么是关联子查询,什么是非关联子查询 (嵌套查询)
    子查询从数据表中查询了数据结果,如果这个数据结果只执行一次,然后这个数据结果作为主查询的条件进行执行,那么这样的子查询叫做非关联子查询。

    如果子查询需要执行多次,即采用循环的方式,先从外部查询开始,每次都传入子查询进行查询,然后再将结果反馈给外部,这种嵌套的执行方式就称为关联子查询。

    哪个球员的身高最高,最高身高是多少,就可以采用子查询的方式:
    -- 非关联子查询示例
    select player_name, height FROM player where height = (select max(height) from player);
    首先通过select max(height) from player 得到最高身高这个数值,然后再将这个值在player表中匹配查找,看谁符合这个值,进行输出。

    查询每个球队中大于平均身高的球员有哪些,并显示他们的球员姓名、身高以及所在球队 ID。
    -- 关联子查询示例
    select player_name, height, team_id from player as a where height > (select avg(height) from player as b where a.team_id = b.team_id);
    如果子查询的执行依赖于外部查询,通常情况下都是因为子查询中的表用到了外部的表,并进行了条件关联,因此每执行一次外部查询,子查询都要重新计算一次,这样的子查询就称之为关联子查询

    (2) EXISTS子查询
    想要看出场过的球员都有哪些,并且显示他们的姓名、球员 ID 和球队 ID。在这个统计中,是否出场是通过 player_score 这张表中的球员出场表现来统计的,如果某个球员在 player_score 中有出场记录则代表他出场过,这里就使用到了 EXISTS 子查询,
    select player_name, player_id, team_id from player where exists (select player_id from player_score where player.player_id = player_score.player_id);
    查询球员不存在于player_score表中的数据
    select player_name, player_id, team_id from player where not exists (select player_id from player_score where player.play_id = player_score.player_id);

    (3) 集合比较子查询-- 与另一个查询结果集进行比较
    主要查询操作符及定义:
    IN 判断是否在集合中
    ANY 需要与操作符一起使用,与子查询返回的任何值做比较
    ALL 需要与操作符一起使用,与子查询返回的所有值做比较
    SOME 实际上是ANY的别名,作用相同,一般尝试用ANY

    想要看出场过的球员都有哪些,并且显示他们的姓名、球员 ID 和球队 ID。
    select player_name, player_id, team_id from player where player_id in (select player_id from player_score where player.player_id = player_score.player_id);

    不难看出,IN操作符和EXISTS操作符的查询结果是一致的,那么应该如何选择IN和EXISTS?

    SELECT * FROM A WHERE cc IN (SELECT cc FROM B)
    SELECT * FROM A WHERE EXIST (SELECT cc FROM B WHERE B.cc=A.cc)
            实际上在查询过程中,在我们对 cc 列建立索引的情况下,我们还需要判断表 A 和表 B 的大小。在这里例子当中,表 A 指的是 player 表,表 B 指的是 player_score 表。如果表 A 比表 B 大,那么 IN 子查询的效率要比 EXIST 子查询效率高,因为这时 B 表中如果对 cc 列进行了索引,那么 IN 子查询的效率就会比较高。同样,如果表 A 比表 B 小,那么使用 EXISTS 子查询效率会更高,因为我们可以使用到 A 表中对 cc 列的索引,而不用从 B 中进行 cc 列的查询。

    ANY 和 ALL 都需要使用比较符,比较符包括了(>)(=)(<)(>=)(<=)和(<>)等。
    查询球员表中,比印第安纳步行者(对应的 team_id 为 1002)中任何一个球员身高高的球员的信息,并且输出他们的球员 ID、球员姓名和球员身高
    select player_name, player_id, team_id, height from player where height > any (select height from player where team_id = 1002);

    查询比印第安纳步行者(对应的 team_id 为 1002)中所有球员身高都高的球员的信息,并且输出球员 ID、球员姓名和球员身高
    select team_id, player_id, player_name, height from player where height > all (select height from player where team_id = 1002);

    请注意:ANY、ALL 关键字必须与一个比较操作符一起使用。因为如果你不使用比较操作符,就起不到集合比较的作用,那么使用 ANY 和 ALL 就没有任何意义

    (4) 将子查询作为计算字段

    实际上子查询也可以作为主查询的计算字段。
    查询每个球队的球员数,也就是对应 team 这张表,我需要查询相同的 team_id 在 player 这张表中所有的球员数量是多少。
    select team_name, (select count(*) from player where player.team_id = team.team_id) as player_num from team;

    在 player 表中只有底特律活塞和印第安纳步行者的球员数据,所以它们的 player_num 不为 0,而亚特兰大老鹰的 player_num 等于 0。在查询的时候,我将子查询SELECT count(*) FROM player WHERE player.team_id = team.team_id作为了计算字段,通常我们需要给这个计算字段起一个别名,这里我用的是 player_num,因为子查询的语句比较长,使用别名更容易理解。

    查询得到场均得分大于 20 的球员。场均得分从 player_score 表中获取,同时你需要输出球员的 ID、球员姓名以及所在球队的 ID 信息
    -- 使用IN
    select team_id, player_id, player_name from player where player_id in (select player_id from player_score GROUP BY player_id HAVING(avg(score) > 20));
    -- 使用EXISTS
    select team_id, player_id, player_name from player where exists (select player_id from player_score GROUP BY player_id HAVING(avg(score) > 20) and player.player_id = player_score.player_id);

    select team_id, player_id, player_name from player where exists (select player_id from player_score where player.player_id = player_score.player_id GROUP BY player_id HAVING avg(score) > 20);
    -- 使用JOIN
    SELECT
    t2.player_id,
    t2.player_name,
    t2.team_id,
    t3.v
    FROM
    player AS t2
    JOIN (
    SELECT
    t1.player_id,
    avg( t1.total ) AS v
    FROM
    (
    SELECT
    player_id,
    sum( score ) AS total
    FROM
    player_score
    WHERE
    game_id IN ( SELECT game_id FROM player_score GROUP BY game_id )
    GROUP BY
    player_id #对球员分组,计算在每场比赛中的总分数
    ) AS t1
    GROUP BY
    t1.player_id #对球员分组,计算所参加比赛的平均数
    HAVING
    v > 20 #场均得分大于20
    ) AS t3 ON t2.player_id = t3.player_id;

    1、我理解的场均得分大于20,第一场得了40分,第二场得了2分,场均为21分满足条件
    2、一场比赛中,球员可以出现多次
    解析思路,先得出球员在每场比赛中的总分数,然后对球员分组,计算球员在所参加比赛中的平均数



  • 相关阅读:
    iOS 9之后Url链接的NSUTF8StringEncoding转码实现
    iOS实现应用更新及强制更新
    Objective-C代码简写
    Mac下使用数据库将Excel数据转换存入.plist
    iOS开发之图片压缩实现
    iOS键盘事件实现、控制
    iOS 轻击、触摸和手势的检测
    使用CocoaPods时遇到 Permission denied 问题
    2016-3-1 Mac下使用Hexo搭建Blog
    2016-3-1 安装Hexo过程中遇到的问题
  • 原文地址:https://www.cnblogs.com/Tom-tao/p/11871142.html
Copyright © 2011-2022 走看看