SQL学习及习题答案( XUESQL)

1.SELECT 查询

请列出所有电影的ID,名称和出版国

SELECT title,id,'美国' as country FROM movies

SQL Lesson 7: 外连接(OUTER JOINs)

INNER JOIN 只会保留两个表都存在的数据(还记得之前的交集吗),这看起来意味着一些数据的丢失,在某些场景下会有问题.

真实世界中两个表存在差异很正常,所以我们需要更多的连表方式,也就是本节要介绍的左连接LEFT JOIN,右连接RIGHT JOIN 和 全连接FULL JOIN. 这几个 连接方式都会保留不能匹配的行。

用LEFT/RIGHT/FULL JOINs 做多表查询

SELECT column, another_column, … FROM mytable **INNER/LEFT/RIGHT/FULL JOIN another_table    ON mytable.id = another_table.matching_id** WHERE *condition(s)* ORDER BY column, … ASC/DESC LIMIT num_limit OFFSET num_offset;

INNER JOIN 语法几乎是一样的. 我们看看这三个连接方法的工作原理:
在表A 连接 B, LEFT JOIN保留A的所有行,不管有没有能匹配上B 反过来 RIGHT JOIN则保留所有B里的行。最后FULL JOIN 不管有没有匹配上,同时保留A和B里的所有行

我们还是可以用集合的图示来描述:
LEFT JOIN
RIGHT JOIN 反过来
FULL JOIN

将两个表数据1-1连接,保留A或B的原有行,如果某一行在另一个表不存在,会用 NULL来填充结果数据。所有在用这三个JOIN时,你需要单独处理 NULL. 关于 NULL 下一节会做更详细的说明

小贴士?

这些Join也可以写作 LEFT OUTER JOIN, RIGHT OUTER JOIN, 或 FULL OUTER JOIN, 和 LEFT JOIN, RIGHT JOIN, and FULL JOIN 等价.

练习

我们会用两个新的表雇员表 Employees 和 办公室表 Buildings. 有一些办公室是新的,还没有雇员.

注意:因为我们这个练习DB的限制,只可以用 LEFT JOIN来解决问题.

Table: Employees (Read-Only)

Role Name Building Years_employed
Engineer Becky A. 1e 4
Engineer Dan B. 1e 2
Engineer Sharon F. 1e 6
Engineer Dan M. 1e 4
Engineer Malcom S. 1e 1
Artist Tylar S. 2w 2
Artist Sherman D. 2w 8
Artist Jakob J. 2w 6
Artist Lillia A. 2w 7
Artist Brandon J. 2w 7
Manager Scott K. 1e 9
Manager Shirlee M. 1e 3
Manager Daria O. 2w 6
Engineer Yancy I. null 0
Artist Oliver P. null 0

Table: Buildings (Read-Only)

Building_name Capacity
1e 24
1w 32
2e 16
2w 20

练习 do it — 请完成如下任务

  1. 找到所有有雇员的办公室(buildings)名字

    两种都可以通过。居然没用left,奇怪

    ① SELECT DISTINCT building FROM employees where building is not null
    ② SELECT distinct e.Building FROM employees ejoin Buildings bon e.Building= b.Building_name
    
  2. 找到所有办公室和他们的最大容量

    SELECT * FROM Buildings;
    
  3. 找到所有办公室里的所有角色(包含没有雇员的),并做唯一输出(DISTINCT)

    开始没想到角色是什么…

    SELECT distinct b.building_name, e.Role
    FROM buildings b
    left join employees e
    on b.Building_name = e.Building
    
  4. 找到所有有雇员的办公室(buildings)和对应的容量

    在上一题的基础上:

    SELECT distinct b.*
    FROM buildings b
    left join employees e
    on b.Building_name = e.Building
    where e.Role is not null
    

SQL Lesson 8: 关于特殊关键字 NULLs

之前我们已经接触过NULL. 在数据库中,NULL表达的是 "无"的概念,或者说没有东西。因为 NULL的存在,我们需要在编写SQL时考虑到某个属性列可能是 NULL的情况, 这种特殊性会造成编写SQL的复杂性,所以没有必要的情况下,我们应该尽量减少 NULL的使用,让数据中尽可能少出现 NULL的情况。

如果某个字段你没有填写到数据库,很可能就会出现NULL 。所有一个常见的方式就是为字段设置默认值,比如 数字的默认值设置为0,字符串设置为 ""字符串. 但是在一些NULL 表示它本来含义的场景,需要注意是否设置默认值还是保持NULL。 (比如, 当你计算一些行的平均值的时候,如果是0会参与计算导致平均值差错,是NULL则不会参与计算).

还有一些情况很难避免 NULL 的出现, 比如之前说的 outer-joining 多表连接,A和B有数据差异时,必须用 NULL 来填充。这种情况,可以用IS NULLIS NOT NULL 来选在某个字段是否等于 NULL.

在查询条件中处理 NULL

SELECT column, another_column, …
FROM mytable **
WHERE column IS/IS NOT NULL**
AND/OR *another_condition* AND/OR …;

练习

还是会用到 EmployeesBuildings 两个表,这一次我们雇佣了一些雇员但还没有分配办公室. 你需要综合之前的知识来解决这些问题!

练习 do it — 请完成如下任务

  1. 找到雇员里还没有分配办公室的(列出名字和角色就可以)

    SELECT name, Role FROM employees
    where Building is null;
    
  2. 找到还没有雇员的办公室

    SELECT b.building_name FROM buildings b
    left join employees e
    on e.Building = b.Building_name
    where e.Role is null;
    

SQL Lesson 9: 在查询中使用表达式

Table: movies (Read-only)

Id Title Director Year Length_minutes
1 Toy Story John Lasseter 1995 81
2 A Bug’s Life John Lasseter 1998 95
3 Toy Story 2 John Lasseter 1999 93
4 Monsters, Inc. Pete Docter 2001 92
5 Finding Nemo Finding Nemo 2003 107
6 The Incredibles Brad Bird 2004 116
7 Cars John Lasseter 2006 117
8 Ratatouille Brad Bird 2007 115
9 WALL-E Andrew Stanton 2008 104
10 Up Pete Docter 2009 101
11 Toy Story 3 Lee Unkrich 2010 103
12 Cars 2 John Lasseter 2011 120
13 Brave Brenda Chapman 2012 102
14 Monsters University Dan Scanlon 2013 110

Table: boxoffice (Read-only)

Movie_id Rating Domestic_sales International_sales
5 8.2 380843261 555900000
14 7.4 268492764 475066843
8 8 206445654 417277164
12 6.4 191452396 368400000
3 7.9 245852179 239163000
6 8 261441092 370001000
9 8.5 223808164 297503696
11 8.4 415004880 648167031
1 8.3 191796233 170162503
7 7.2 244082982 217900167
10 8.3 293004164 438338580
4 8.1 289916256 272900000
2 7.2 162798565 200600000
13 7.2 237283207 301700000
  1. 列出所有的电影ID,名字和销售总额(以百万美元为单位计算)

    SELECT id,title,(Domestic_sales+International_sales)/1000000  FROM movies m
    join boxoffice b
    on m.id = b.Movie_id;
    
  2. 列出所有的电影ID,名字和市场指数(Rating的10倍为市场指数)

    SELECT id,title,Rating*10  FROM movies m
    join boxoffice b
    on m.id = b.Movie_id;
    
  3. 列出所有偶数年份的电影,需要电影ID,名字和年份

    SELECT id,title,year  FROM movies m
    join boxoffice b
    on m.id = b.Movie_id
    where year%2=0
    
  4. John Lasseter导演的每部电影每分钟值多少钱,告诉我最高的3个电影名和价值就可以

    SELECT title,(Domestic_sales+International_sales)/Length_minutes FROM movies m
    join boxoffice b
    on b.Movie_id = m.id
    where director = 'John Lasseter'
    order by (Domestic_sales+International_sales)/Length_minutes desc
    limit 3 ;
    
  5. 电影名最长的3部电影和他们的总销量是多少

    没想到还要把长度打印出来… length():求字符串长度

    SELECT title,length(m.Title),(Domestic_sales+
    International_sales) FROM movies m
    join boxoffice b
    on b.Movie_id = m.id
    order by length(m.Title) desc
    limit 3
    

SQL Lesson 10: 在查询中进行统计I (Pt. 1)

下面介绍几个常用统计函数:

Function Description
COUNT(*), COUNT(column) 计数!COUNT(*) 统计数据行数,COUNT(column) 统计column非NULL的行数.
MIN(column) 找column最小的一行.
MAX(column) 找column最大的一行.
**AVG(**column) 对column所有行取平均值.
SUM(column) 对column所有行求和.

分组函数自动忽略null

分组统计

GROUP BY 数据分组语法可以按某个col_name对数据进行分组,如:GROUP BY Year指对数据按年份分组, 相同年份的分到一个组里。如果把统计函数和GROUP BY结合,那统计结果就是对分组内的数据统计了.
GROUP BY 分组结果的数据条数,就是分组数量,比如:GROUP BY Year,全部数据里有几年,就返回几条数据, 不管是否应用了统计函数.

  1. 找出就职年份最高的雇员(列出雇员名字+年份)

    SELECT name,Years_employed FROM employees
    order by Years_employed desc
    limit 1

  2. 按角色(Role)统计一下每个角色的平均就职年份

    SELECT role,avg(Years_employed) FROM employees
    group by role

  3. 按办公室名字总计一下就职年份总和
    SELECT building,sum(Years_employed) FROM employees
    group by building

  4. 每栋办公室按人数排名,不要统计无办公室的雇员

    观察Building里有两个为null的,去掉它们。分组后用count统计行数

    select Building,count(Building) from Employees
    where Building is not null
    group by Building
    
  5. 就职1,3,5,7年的人分别占总人数的百分比率是多少(给出年份和比率"50%" 记为 50)

    ①求出总人数select count(*)from employees

    ②选Years_employed,与其对应的人数
    这里第一个count(*)算的是分组之后的对应人数

    经过评论区指正,我一开始写的这个是错误的:×

    select Years_employed,count(*)*100/(select count(*)from employees) as Rating
    from Employees
    where Years_employed in (1,3,5,7)
    group by Years_employed
    

    正确SQL:

    select Years_employed, ROUND(count(*)*1.0*100/(select count(*)from employees) ) as Rating
    from Employees
    where Years_employed in (1,3,5,7)
    group by Years_employed
    

    原因:没有乘1.0 和用round函数(没想到要四舍五入)
    加上 *1.0 之后:可以看到是除不尽的…

SQL Lesson 11: 在查询中进行统计II (Pt. 2)

我们将更加深入的分析 Employee 数据,综合运用不同的SQL语法来解决这些问题.

Role Name Building Years_employed
Engineer Becky A. 1e 4
Engineer Dan B. 1e 2
Engineer Sharon F. 1e 6
Engineer Dan M. 1e 4
Engineer Malcom S. 1e 1
Artist Tylar S. 2w 2
Artist Sherman D. 2w 8
Artist Jakob J. 2w 6
Artist Lillia A. 2w 7
Artist Brandon J. 2w 7
Manager Scott K. 1e 9
Manager Shirlee M. 1e 3
Manager Daria O. 2w 6
Engineer Yancy I. null 0
Artist Oliver P. null 0
  1. 统计一下Artist角色的雇员数量

    方法①:把Artist的查询结果当作临时表

    SELECT count(*) FROM (select * from employees where role = 'Artist');
    

    方法②:按角色role先分组,再求和

    select count(role)
    from employees
    where role = 'Artist'
    group by role;
    
  2. 按角色统计一下每个角色的雇员数量

    SELECT role ,count(*) FROM employees
    group by role;
    
  3. 算出Engineer角色的就职年份总计

    SELECT sum(Years_employed) FROM employees
    where role = 'Engineer'
    group by role;
    

4.按角色分组算出每个角色按有办公室和没办公室的统计人数(列出角色,数量,有无办公室,注意一个角色如果部分有办公室,部分没有需分开统计)

①按照题目要求,按角色、是否有办公室来分组 ②统计case when,如果是null要填0,有则填1。这里第二种方法is not null为1就有办公室

SELECT role,count(*),
case when building is null then'0' else '1' end  as have_Building
FROM employees
group by role, building is null
SELECT count(*) as count,Role,building is not null as have_building
FROM employees
group by Role,building is not null

5.按角色和就职年份统计人数,年份按0-3,3-6,6-9这种阶梯分组,最后按角色+阶梯分组排序

年份分组就是“除以3”

SELECT Role,Years_employed/3 as year_3,count(*) as count
FROM employees
group by Role,year_3
order by count esc
SELECT role,count(*),Years_employed/3
FROM employees
group by role,Years_employed/3 ;

SQL Lesson 12: 查询执行顺序

这才是完整的SELECT查询

要记住书写的顺序

SELECT DISTINCT column, AGG_FUNC(column_or_expression), …
FROM mytableJOIN another_tableON mytable.column = another_table.columnWHERE constraint_expressionGROUP BY columnHAVING constraint_expressionORDER BY column ASC/DESCLIMIT count OFFSET COUNT;

查询执行顺序

1. FROMJOINs

FROMJOIN会第一个执行,确定一个整体的数据范围. 如果要JOIN不同表,可能会生成一个临时Table来用于 下面的过程。总之第一步可以简单理解为确定一个数据源表(含临时表)

2. WHERE

我们确定了数据来源 WHERE 语句就将在这个数据源中按要求进行数据筛选,并丢弃不符合要求的数据行,所有的筛选col属性 只能来自FROM圈定的表. AS别名还不能在这个阶段使用,因为可能别名是一个还没执行的表达式

3. GROUP BY

如果你用了 GROUP BY 分组,那GROUP BY 将对之前的数据进行分组,统计等,并将是结果集缩小为分组数.这意味着 其他的数据在分组后丢弃.

4.HAVING

如果你用了 GROUP BY 分组, HAVING 会在分组完成后对结果集再次筛选。AS别名也不能在这个阶段使用.

5. SELECT

确定结果之后,SELECT用来对结果col简单筛选或计算,决定输出什么数据.

6. DISTINCT

如果数据行有重复DISTINCT 将负责排重.

7. ORDER BY

在结果集确定的情况下,ORDER BY 对结果做排序。因为SELECT中的表达式已经执行完了。此时可以用AS别名.

8. LIMIT / OFFSET

最后 LIMITOFFSET 从排序的结果中截取部分数据

练习 do it — 请完成如下任务

  1. 统计出每一个导演的电影数量(列出导演名字和数量)

    SELECT Director,count(*) FROM movies m
    join boxoffice b
    on m.id  = b.Movie_id
    group by m.Director;
    
  2. 统计一下每个导演的销售总额(列出导演名字和销售总额)

    SELECT Director,sum(Domestic_sales+International_sales) FROM movies m
    join boxoffice b
    on m.id  = b.Movie_id
    group by m.Director;
    
  3. 按导演分组计算销售总额,求出平均销售额冠军(统计结果过滤掉只有单部电影的导演,列出导演名,总销量,电影数量,平均销量)

    ①分组group by director;销售总额用sum(Domestic_sales+International_sales)

    ②**平均销售额**:总销售额/总数

    ③过滤再排序

    SELECT director,count(*),sum(Domestic_sales+International_sales) as sum_sale,sum(Domestic_sales+International_sales)/count(*) as avg_sale
    FROM movies m
    left join boxoffice b
    on m.id = b.movie_id
    group by director
    having count(*) > 1
    order by avg_sale desc limit 1
    
  4. 找出每部电影和单部电影销售冠军之间的销售差,列出电影名,销售额差额

    ①找 单部电影销售冠军值:1063171911

    ②比较销售差(相减)

    SELECT title,
    (SELECT (Domestic_sales+
    International_sales) FROM movies m
    join boxoffice b
    on m.id = b.movie_id
    order by(Domestic_sales+
    International_sales) desc limit 1)- (Domestic_sales+International_sales) as sale_diff
    FROM movies m
    left join boxoffice b
    on m.id = b.movie_id
    order by sale_diff desc  //可以不写
    

XUESQL-自学SQL网站上的练习题相关推荐

  1. 可能是史上最适合入门SQL语句的教程——自学SQL网学习笔记

    自学SQL网Note 学习网址:http://xuesql.cn/ 表格.题目和知识点采集于自学SQL网,这个网站提供直接练习SQL的页面,免去了安装MySQL和导入表格的繁琐步骤,非常推荐初学者学习 ...

  2. 推荐一个学习SQL的网站-自学SQL网

    自学SQL网 自学SQL网 一个适合小白学SQL的网站,由浅入深的介绍所有有关 SQL 的知识, 每一个章节是一组相关的SQL知识点: 并且会配备一组动手练习任务. 这个网站特别适合学完某种知识就想马 ...

  3. SQL Server 2005全文检索技术在网站上的应用实录

    SQL Server 2005全文检索技术在网站上的应用实录 一.前言 "人类失去搜索,世界将会怎样?",同样,很难想象一个拥有极大信息量的行业网站门户没有站内全文搜索将会出现怎样 ...

  4. 自学SQL网习题题解:0-12(带内容解析!)

    自学SQL网习题题解:0-12(带内容解析!) 原创:丶无殇  2022-07-17 这是一个自学SQL的中文网站,基础内容质量高,语言简洁明了,能够快速学习并提升技能. 网址:http://xues ...

  5. 自学SQL网之学习笔记(题目+答案)

    最近在重新学习数据库SQL,这里分享一下在使用<自学SQL网>上自学期间所涉及的练习题. 重要的事情要说三遍!仅供参考!仅供参考!仅供参考!!! 当然也悄悄种草一下这个网站练练手还是蛮不错 ...

  6. 推荐几个适合新手入门学习的SQL网站,在线就能练习

    这里整理推荐几个我自己学习时用过的在线学习网站,对新手非常友好,帮助初学者快速入门SQL,在交互式的环境里学习,既不用安装也不用导入数据,在线就能思考和练习. 1.自学SQL网 适合小白学习,这里由浅 ...

  7. 我使用Python和Django在自己的网站上建立了一个会员专区。 这是我学到的东西。

    I decided it was time to upgrade my personal website in order to allow visitors to buy and access my ...

  8. 自学python网站推荐-推荐自学python必入的神仙网站

    现在没点技术,工作想要6000+太难了,想要挣钱,就必须让自己值钱,想要自学python必知的网站分享,每一个网站上都有自学的文章和教程,不花一分钱,自学python入门,为自己增值. 1.什么是Py ...

  9. 网站搜索功能怎么实现_电商网站上的搜索功能是如何实现的?

    今天是刘小爱自学Java的第159天. 感谢你的观看,谢谢你. 学习计划安排如下: 索引库本质上和数据库类似,也是存储数据的,既然如此自然也会有增删改查. 那么这个索引库到底有何特别应用呢? 索引库的 ...

最新文章

  1. 实验一:SQL server 2005高可用性之----日志传送
  2. 是什么动词_动词后面跟什么词?答案笑喷...
  3. 光在介质中传播速度—材料折射率变化—物理光学记录
  4. Android控件之ConstraintLayout详解
  5. 漫画:深入浅出 ES 模块
  6. Chrome 键盘快捷键(Mac)
  7. CentOS 5 安装免费虚拟主机管理系统Kloxo
  8. 跑三小时的monkey测试该怎么算_浅谈App测试(下)~带音频
  9. emacs编辑器的使用
  10. Java 常用工具类 - 校验银行卡号 BankCardUtils
  11. springboot添加ojdbc6报错
  12. 【软件工程】-项目开发计划
  13. Hive On Spark搭建报错:Failed to create Spark client for Spark session xx: ..TimeoutException
  14. 一、物流的基本概念|1.1物流的定义及作用
  15. unparseable date:‘’
  16. sx1278lora模块的常见问题解答
  17. 【第2期免费送书】 10本机器学习与Python相关书籍等你来领!经典之作,绝对领你心动......
  18. 最全的Android单元测试教程
  19. 教你用Java来玩答题(百万英雄/冲刺大会等)
  20. 服务器集群及其优缺点!

热门文章

  1. gateway集成nacos、loadbalancer实现自定义负载均衡器,带源码解析(cloud版本:2021.0.3|boot版本:2.7.4)[场景1:灰度发布(金丝雀发布)]
  2. 在 yoga pro 14s 2022 上安装 Ubuntu 20.04.6
  3. PBOC/EMV之DDA(动态数据认证)
  4. vue 实战 之 饿了吗 页头模板
  5. 中国(上海)国际人工智能展览会,极链科技Video++获技术创新奖
  6. gis微水在线监测服务器,GIS 微水密度在线监测技术方案.doc
  7. NYOJ_779兰州烧饼
  8. Echarts分级柱状图
  9. #if (DEBUG)
  10. 【4】多线程之间实现通讯