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

原创:丶无殇  2022-07-17


这是一个自学SQL的中文网站,基础内容质量高,语言简洁明了,能够快速学习并提升技能。

网址:http://xuesql.cn/

本文为每题做了详细的解析!具体如下。



SQL Lesson 0: 让我给SQL做个自我介绍

1. 【初体验】这是第一题,请你先将左侧的输入框里的内容清空,然后请输入下面的SQL,您将看到所有电影标题。

SELECT title FROM movies

解释:select (要显示的列名1,列名2,……) from (要查找的表名)
【关键字前后可以换行,select后可以是:列名、计算式、函数等】

2. 【初体验】请输入如下SQL你将看到4条电影(切记先清空数据框且出错要耐心比对)

SELECT title,director FROM movies WHERE Id < 5

解释:select (要显示的列名1,列名2,……) from (要查找的表名)
where (筛选的条件,如:id小于5)

3. 【初体验】输入如下SQL你将看到电影总条数

SELECT count(*) FROM movies

解释:计算movies表中的记录数量

4. 【初体验】SQL可以直接做计算,下面的SQL计算1+1的和

SELECT 1+1

解释:select 直接加计算式


SQL Lesson 1: SELECT 查询 101

1. 【简单查询】找到所有电影的名称title

SELECT title FROM movies

2. 【简单查询】找到所有电影的导演

SELECT Director FROM movies

3. 【简单查询】找到所有电影的名称和导演

SELECT Title,Director FROM movies

解释:需要输入两列:名称(Title)和导演(Director )

4. 【简单查询】找到所有电影的名称和上映年份

SELECT Title,Year FROM movies

5. 【简单查询】找到所有电影的所有信息

SELECT * FROM movies

解释:输入*符号表示匹配所有内容,在实际应用中尽量不要使用全匹配,如果数据量非常大,会影响速度

6. 【简单查询】找到所有电影的名称,Id和播放时长

SELECT id,Title,Length_minutes FROM movies

解释:我们习惯性的将ID放在第一列


SQL Lesson 2: 条件查询 (constraints) (Pt. 1)

1. 简单条件】找到id为6的电影

SELECT * FROM movies where id=6

解释:条件查询用where

2. 【简单条件】找到在2000-2010年间year上映的电影

SELECT * FROM movies WHERE year BETWEEN 2000 AND 2010

解释:条件查询用where,判断内容的关键字如下表所示:

关键字描述举例
…AND…多个判断内容之间用AND连接id<=6 AND year<2000
=, !=, < <=, >, >=,<>基于数字的大小判断,!=<>都表示不等于id<=6
…BETWEEN…AND…判断在两个数值中间year BETWEEN 2000 AND 2010
…NOT BETWEEN…AND…判断不在两个数值中间year NOT BETWEEN 2000 AND 2010
…IN(…)判断内容在一个列表中year IN(1995,2001,2002,2010)
…NOT IN(…)判断内容不在一个列表中year NOT IN(1995,2001,2002,2010)

3. 【简单条件】找到不是在2000-2010年间year上映的电影

SELECT * FROM movies WHERE year NOT BETWEEN 2000 AND 2010

4. 【简单条件】找到头5部电影

SELECT * FROM movies WHERE id<=5

5. 【简单条件】找到2010(含)年之后的电影里片长小于两个小时的片子

SELECT * FROM movies WHERE year>=2010 AND Length_minutes<120

SQL Lesson 3: 条件查询(constraints) (Pt. 2)

1. 【复杂条件】找到所有Toy Story系列电影

SELECT * FROM movies WHERE title LIKE '%Toy Story%'

解释:系列电影,说明名字类似,但可能有第一部第二部之类的,所以要给他前后匹配一下。
判断内容的关键字如下表所示:

关键字描述举例
=, !=, <>基于数字的大小判断,!=<>都表示不等于name!=‘ABCD’
…LIKE…不加通配符等于=name LIKE ‘ABCD’
…NOT LIKE…不加通配符等于!=<>name NOT LIKE ‘ABCD’
%匹配0个以上的字符name LIKE ‘%BC%’
_(下划线)匹配1个字符name LIKE ‘ABC_’(不能匹配ABC)
…IN(…)判断内容在一个列表中name IN(‘ABCD’,‘HTML’,‘PYTHON’)
…NOT IN(…)判断内容不在一个列表中name NOT IN(‘ABCD’,‘HTML’,‘PYTHON’)

2. 【复杂条件】找到所有John Lasseter导演的电影

SELECT * FROM movies WHERE Director = 'John Lasseter'

解释:查询条件就是导演的名字

3. 【复杂条件】找到所有不是John Lasseter导演的电影

SELECT * FROM movies WHERE Director != 'John Lasseter'

解释:与上一题相反,查询导演名字不是John Lasseter的内容

4. 【复杂条件】找到所有电影名为 “WALL-” 开头的电影

SELECT * FROM movies WHERE title LIKE 'WALL-%'

解释:用到LIKE匹配,开头限定好了之后通配后面的内容

5. 【复杂条件】有一部98年电影中文名《虫虫危机》请给我找出来

SELECT * FROM movies WHERE title LIKE '%Bug%' AND year = 1998

解释:名字中有虫(Bug),可以通过Bug进行全匹配。如果知道名字,可以用以下语句
SELECT * FROM movies WHERE title = 'A Bug''s Life' AND year = 1998
此处的Bug's中的'需要用''来转义


SQL Lesson 4: 查询结果Filtering过滤 和 sorting排序

1. 【结果排序】按导演名排重列出所有电影(只显示导演),并按导演名正序排列

SELECT DISTINCT Director FROM movies ORDER BY Director ASC

解释:DISTINCT作用是排重,重复内容只显示一个;ORDER BY作用是排序,后面接需要排序的列名,ASC表示正序,DESC表示倒序

2. 【结果排序】列出按上映年份最新上线的4部电影

SELECT * FROM movies ORDER BY Year DESC LIMIT 4

解释:首先DESC倒序排序,再用LIMIT限制数量为4。LIMIT…OFFSET…一般用在排序后

3. 【结果排序】按电影名字母序升序排列,列出前5部电影

SELECT * FROM movies ORDER BY Title ASC LIMIT 5

4. 【结果排序】按电影名字母序升序排列,列出上一题之后的5部电影

SELECT * FROM movies ORDER BY Title ASC LIMIT 5 OFFSET 5

解释:LIMIT…OFFSET…一般用在排序后,LIMIT设置筛选数量,OFFSET设置从哪里开始计数

5. 【结果排序】如果按片长排列,John Lasseter导演导过片长第3长的电影是哪部,列出名字即可

SELECT Title FROM movies 
WHERE Director='John Lasseter' 
ORDER BY Length_minutes DESC 
LIMIT 1 OFFSET 2

解释:结果排序一般在按条件查询之后,结果筛选在结果排序之后


SQL Lesson 5(Review): 复习 SELECT综合条件查询

1. 【复习】列出所有加拿大人的Canadian信息(包括所有字段)

SELECT * FROM north_american_cities WHERE Country='Canada'

解释:加拿大人对应的国家名叫Canada,所以筛选时筛选Country='Canada'

**2. 【复习】列出所有在Chicago西部的城市,从西到东排序(包括所有字段) **

SELECT * FROM north_american_cities 
WHERE Longitude<'-87.629798'
ORDER BY Longitude ASC

解释:通过经度判断东西方位

3. 【复习】用人口数population排序,列出墨西哥Mexico最大的2个城市(包括所有字段)

SELECT * FROM north_american_cities ,
WHERE Country='Mexico'
ORDER BY Population DESC
LIMIT 2

4. 【复习】列出美国United States人口3-4位的两个城市和他们的人口(包括所有字段)

SELECT * FROM north_american_cities ,
WHERE Country='United States'
ORDER BY Population DESC
LIMIT 2 OFFSET 2

SQL Lesson 6: 用JOINs进行多表联合查询

1. 【联表】找到所有电影的国内Domestic_sales和国际销售额

SELECT * FROM movies INNER JOIN Boxoffice ON Movies.id=Boxoffice.Movie_id

解释:两张表的内容通过联表查询

关键字描述
INNER JOIN…ON…=…内连接,通过某个属性连接,两表无对应的数据会舍弃
LEFT JOIN…ON…=…左连接,通过某个属性连接,右表无对应的数据会舍弃
RIGHT JOIN…ON…=…右连接,通过某个属性连接,左表无对应的数据会舍弃
FULL JOIN …ON…=…全连接,通过某个属性连接,两表无对应的数据会保留

2. 【联表】找到所有国际销售额比国内销售大的电影

SELECT * FROM movies INNER JOIN Boxoffice ON Movies.id=Boxoffice.Movie_id
WHERE International_sales>Domestic_sales

解释:对联表后的表做查询

3. 【联表】找出所有电影按市场占有率rating倒序排列

SELECT * FROM movies INNER JOIN Boxoffice ON Movies.id=Boxoffice.Movie_id
ORDER BY Rating DESC

4. 【联表】每部电影按国际销售额比较,排名最靠前的导演是谁,国际销量多少

SELECT Director,International_sales FROM movies 
INNER JOIN Boxoffice ON Movies.id=Boxoffice.Movie_id
ORDER BY International_sales DESC LIMIT 1

SQL Lesson 7: 外连接(OUTER JOINs)

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

SELECT DISTINCT Building FROM employees WHERE Building IS NOT NULL

解释:查找名字,重复内容只显示一个即可,所以用DISTINCT;判断有雇员的,即不为空(IS NOT NULL

2. 【复习】找到所有办公室里的所有角色(包含没有雇员的),并做唯一输出(DISTINCT)

SELECT DISTINCT Building_name,Role FROM Buildings
LEFT JOIN employees ON Employees.Building=Buildings.Building_name

解释:基础数据为办公室,所以查表FROM办公室,包含没有雇员的,所以用LEFT JOIN可以包含NULL

3. 【难题】找到所有有雇员的办公室(buildings)和对应的容量

SELECT DISTINCT Building,Capacity FROM Buildings
LEFT JOIN employees ON Employees.Building=Buildings.Building_name
WHERE Building IS NOT NULL

解释:有雇员的办公室,需要排除为NULL


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

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

SELECT Name,Role FROM employees
WHERE Building IS NULL

解释:从雇员表中查找办公室为NULL

2. 【难题】找到还没有雇员的办公室

SELECT Building_name FROM Buildings 
LEFT JOIN Employees ON Employees.Building=Buildings.Building_name
WHERE Role IS NULL

解释:从办公室表中查找雇员角色为NULL


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

1. 【计算】列出所有的电影ID,名字和销售总额(以百万美元为单位计算)

SELECT ID,Title,(Domestic_sales+International_sales)/1000000  FROM movies
LEFT JOIN Boxoffice ON Boxoffice.Movie_id=Movies.id

解释:以百万为单位,就要除以1000000,并关联销售数据表

2. 【计算】列出所有的电影ID,名字和市场指数(Rating的10倍为市场指数)

SELECT ID,Title,Rating*10  FROM movies
LEFT JOIN Boxoffice ON Boxoffice.Movie_id=Movies.id

3. 【计算】列出所有偶数年份的电影,需要电影ID,名字和年份

SELECT ID,Title,Year FROM movies WHERE Year%2=0

解释:偶数判断,用年份取余2,结果为零的即偶数

4. 【难题】John Lasseter导演的每部电影每分钟值多少钱,告诉我最高的3个电影名和价值就可以

SELECT Title,(Domestic_sales+International_sales)/Length_minutes FROM movies 
LEFT JOIN Boxoffice ON Boxoffice.Movie_id=Movies.id
WHERE Director='John Lasseter'
ORDER BY (Domestic_sales+International_sales)/Length_minutes DESC
LIMIT 3

解释:先选择要显示的列名与要关联的表,筛选出John Lasseter导演的,再通过每分钟的价值倒序排序,最后选择出3个


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

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

SELECT Name,Max(Years_employed) FROM employees 

解释:求最大值,用max()函数

函数名描述
COUNT(*),COUNT(列名)COUNT(*) 统计数据行数,COUNT(列名) 统计column非NULL的行数
MIN(列名)找到最小值
MAX(列名)找到最大值
AVG(列名)计算平均值
SUM(列名)求出总和

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

SELECT Role,avg(Years_employed) FROM employees GROUP BY Role

解释:按某部分分组,使用GROUP BY进行过滤,平均值用avg()函数

3. 【分组】按办公室名字总计一下就职年份总和

SELECT Building,sum(Years_employed) FROM employees GROUP BY Building

解释:求和函数用sum()

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

SELECT Building,count(Building) FROM employees 
WHERE Building IS NOT NULL
GROUP BY Building

解释:按人数排名,需要计算办公室的人数总和,用count(Building)计算;同时不要无办公室的雇员,所以WHERE判断Building不为空;要按照每栋办公室排,则用GROUP BY过滤出Building


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

1. 【统计】统计一下Artist角色的雇员数量

SELECT count(*) FROM employees WHERE Role='Artist'

2. 【分组】按角色统计一下每个角色的雇员数量

SELECT Role,count(*) FROM employees GROUP BY Role

3. 【分组】算出Engineer角色的就职年份总计

SELECT sum(Years_employed) FROM employees WHERE Role='Engineer'

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

SELECT Role,count(*),building IS NOT NULL AS hasBuilding
FROM employees GROUP BY role,hasBuilding

解释:有无办公室可用Building IS NOT NULL来判断,用AS可以为当前列名赋一个新的名字;为了区别开有无办公室,需要将有无办公室也加入GROUP BY


SQL Lesson 12: 查询执行顺序

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

SELECT Director,count(*) FROM movies GROUP BY Director

2. 【复习】统计一下每个导演的销售总额(列出导演名字和销售总额)

SELECT Director,sum(Domestic_sales+International_sales) as total FROM movies 
LEFT JOIN Boxoffice ON Movies.id=Boxoffice.Movie_id
GROUP BY Director

3. 【难题】按导演分组计算销售总额,求出平均销售额冠军(统计结果过滤掉只有单部电影的导演,列出导演名,总销量,电影数量,平均销量)

SELECT 
	Director,
	sum(Domestic_sales+International_sales) as total,
	count(*),
	sum(Domestic_sales+International_sales)/count(*) as avg
FROM movies 
LEFT JOIN Boxoffice ON Movies.id=Boxoffice.Movie_id
GROUP BY Director
HAVING count(*)>1
ORDER BY avg DESC
LIMIT 1

解释:首先通过LEFT JOIN联表查询列出导演,总销量,电影数量,平均销量;然后按照导演分组GROUP BY
如果你用了 GROUP BY 分组, HAVING 会在分组完成后对结果集再次筛选,用HAVING 过滤出只有单部电影的导演;最后将平均销量倒序排序,取出第一条

4. 【变态难】找出每部电影和单部电影销售冠军之间的销售差,列出电影名,销售额差额

-- 先求销冠
-- SELECT max(Domestic_sales+International_sales) FROM Boxoffice 

SELECT 
	Title,
	(SELECT max(Domestic_sales+International_sales) FROM Boxoffice)-
	(Domestic_sales+International_sales) as diff
FROM movies 
LEFT JOIN Boxoffice ON Movies.id=Boxoffice.Movie_id
GROUP BY Title

解释:先求销冠SELECT max(Domestic_sales+International_sales) FROM Boxoffice,然后用销冠与销售额做差


题解至此结束,如果有解释错误的地方,可以评论说明。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐