自学SQL网习题题解:0-12(带内容解析!)
原创:丶无殇 2022-07-17
这是一个自学SQL的中文网站,基础内容质量高,语言简洁明了,能够快速学习并提升技能。
网址:http://xuesql.cn/
本文为每题做了详细的解析!具体如下。
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 直接加计算式
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
放在第一列
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
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
中的'
需要用''
来转义
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
解释:结果排序一般在按条件查询之后,结果筛选在结果排序之后
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
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
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
的
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
的
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个
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
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
中
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
,然后用销冠与销售额做差
题解至此结束,如果有解释错误的地方,可以评论说明。