SQL 刷题 Views
表:
1 2 3 4 5 6 7 8 9 10 11 +---------------+---------+ | Column Name | Type | +---------------+---------+ | article_id | int | | author_id | int | | viewer_id | int | | view_date | date | +---------------+---------+ 此表可能会存在重复行。(换句话说,在 SQL 中这个表没有主键) 此表的每一行都表示某人在某天浏览了某位作者的某篇文章。 请注意,同一人的 author_id 和 viewer_id 是相同的。
请查询出所有浏览过自己文章的作者
结果按照 id
升序排列。
查询结果的格式如下所示:
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 输入: Views 表: +------------+-----------+-----------+------------+ | article_id | author_id | viewer_id | view_date | +------------+-----------+-----------+------------+ | 1 | 3 | 5 | 2019-08-01 | | 1 | 3 | 6 | 2019-08-02 | | 2 | 7 | 7 | 2019-08-01 | | 2 | 7 | 6 | 2019-08-02 | | 4 | 7 | 1 | 2019-07-22 | | 3 | 4 | 4 | 2019-07-21 | | 3 | 4 | 4 | 2019-07-21 | +------------+-----------+-----------+------------+ 输出: +------+ | id | +------+ | 4 | | 7 | +------+
解法:
1 2 3 4 5 6 7 SELECT author_id AS 'id' FROM Views WHERE author_id = viewer_idGROUP BY idORDER BY id
1 select distinct author_id as id from Views where author_id = viewer_id order by id
Insurance
表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +-------------+-------+ | Column Name | Type | +-------------+-------+ | pid | int | | tiv_2015 | float | | tiv_2016 | float | | lat | float | | lon | float | +-------------+-------+ pid 是这张表的主键(具有唯一值的列)。 表中的每一行都包含一条保险信息,其中: pid 是投保人的投保编号。 tiv_2015 是该投保人在 2015 年的总投保金额,tiv_2016 是该投保人在 2016 年的总投保金额。 lat 是投保人所在城市的纬度。题目数据确保 lat 不为空。 lon 是投保人所在城市的经度。题目数据确保 lon 不为空。
编写解决方案报告 2016 年 (tiv_2016
) 所有满足下述条件的投保人的投保金额之和:
他在 2015 年的投保额 (tiv_2015
) 至少跟一个其他投保人在 2015 年的投保额相同。
他所在的城市必须与其他投保人都不同(也就是说 (lat, lon
) 不能跟其他任何一个投保人完全相同)。
tiv_2016
四舍五入的 两位小数 。
查询结果格式如下例所示。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 输入: Insurance 表: +-----+----------+----------+-----+-----+ | pid | tiv_2015 | tiv_2016 | lat | lon | +-----+----------+----------+-----+-----+ | 1 | 10 | 5 | 10 | 10 | | 2 | 20 | 20 | 20 | 20 | | 3 | 10 | 30 | 20 | 20 | | 4 | 10 | 40 | 40 | 40 | +-----+----------+----------+-----+-----+ 输出: +----------+ | tiv_2016 | +----------+ | 45.00 | +----------+ 解释: 表中的第一条记录和最后一条记录都满足两个条件。 tiv_2015 值为 10 与第三条和第四条记录相同,且其位置是唯一的。 第二条记录不符合任何一个条件。其 tiv_2015 与其他投保人不同,并且位置与第三条记录相同,这也导致了第三条记录不符合题目要求。 因此,结果是第一条记录和最后一条记录的 tiv_2016 之和,即 45 。
解法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 SELECT ROUND(SUM (tiv_2016), 2 ) AS tiv_2016FROM InsuranceWHERE tiv_2015 IN ( SELECT tiv_2015 FROM Insurance GROUP BY tiv_2015 HAVING COUNT (* ) > 1 ) AND (lat, lon) NOT IN ( SELECT lat, lon FROM Insurance GROUP BY lat, lon HAVING COUNT (* ) > 1 )
表: Customer
1 2 3 4 5 6 7 8 9 +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | name | varchar | | referee_id | int | +-------------+---------+ 在 SQL 中,id 是该表的主键列。 该表的每一行表示一个客户的 id、姓名以及推荐他们的客户的 id。
找出那些 没有被 id = 2
的客户 推荐 的客户的姓名。
以 任意顺序 返回结果表。
结果格式如下所示。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 输入: Customer 表: +----+------+------------+ | id | name | referee_id | +----+------+------------+ | 1 | Will | null | | 2 | Jane | null | | 3 | Alex | 2 | | 4 | Bill | null | | 5 | Zack | 1 | | 6 | Mark | 2 | +----+------+------------+ 输出: +------+ | name | +------+ | Will | | Jane | | Bill | | Zack | +------+
解法:
1 select name from Customer where referee_id is null or referee_id != 2 ;
表: Orders
1 2 3 4 5 6 7 8 +-----------------+----------+ | Column Name | Type | +-----------------+----------+ | order_number | int | | customer_number | int | +-----------------+----------+ 在 SQL 中,Order_number是该表的主键。 此表包含关于订单ID和客户ID的信息。
查找下了 最多订单 的客户的 customer_number
。
测试用例生成后, 恰好有一个客户 比任何其他客户下了更多的订单。
查询结果格式如下所示。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 输入: Orders 表: +--------------+-----------------+ | order_number | customer_number | +--------------+-----------------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | | 4 | 3 | +--------------+-----------------+ 输出: +-----------------+ | customer_number | +-----------------+ | 3 | +-----------------+ 解释: customer_number 为 '3' 的顾客有两个订单,比顾客 '1' 或者 '2' 都要多,因为他们只有一个订单。 所以结果是该顾客的 customer_number ,也就是 3 。
解法:
1 select customer_number from Orders group by customer_number order by count (customer_number) desc limit 1 ;
1 2 3 4 5 6 7 8 select customer_numberfrom ordersgroup by customer_numberhaving count (order_number)>= all ( select count (order_number) from orders group by customer_number )
表: Triangle
1 2 3 4 5 6 7 8 9 +-------------+------+ | Column Name | Type | +-------------+------+ | x | int | | y | int | | z | int | +-------------+------+ 在 SQL 中,(x, y, z)是该表的主键列。 该表的每一行包含三个线段的长度。
对每三个线段报告它们是否可以形成一个三角形。
以 任意顺序 返回结果表。
查询结果格式如下所示。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 输入: Triangle 表: +----+----+----+ | x | y | z | +----+----+----+ | 13 | 15 | 30 | | 10 | 20 | 15 | +----+----+----+ 输出: +----+----+----+----------+ | x | y | z | triangle | +----+----+----+----------+ | 13 | 15 | 30 | No | | 10 | 20 | 15 | Yes | +----+----+----+----------+
解法:
1 2 3 4 5 6 select x, y, z, case when x + y > z and y + z > x and z + x > y then 'Yes' else 'No' end as triangle from Triangle;
表: Person
1 2 3 4 5 6 7 8 +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | email | varchar | +-------------+---------+ id 是该表的主键列(具有唯一值的列)。 该表的每一行包含一封电子邮件。电子邮件将不包含大写字母。
编写解决方案 删除 所有重复的电子邮件,只保留一个具有最小 id
的唯一电子邮件。
(对于 SQL 用户,请注意你应该编写一个 DELETE
语句而不是 SELECT
语句。)
(对于 Pandas 用户,请注意你应该直接修改 Person
表。)
运行脚本后,显示的答案是 Person
表。驱动程序将首先编译并运行您的代码片段,然后再显示 Person
表。Person
表的最终顺序 无关紧要 。
返回结果格式如下示例所示。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 输入: Person 表: +----+------------------+ | id | email | +----+------------------+ | 1 | john@example.com | | 2 | bob@example.com | | 3 | john@example.com | +----+------------------+ 输出: +----+------------------+ | id | email | +----+------------------+ | 1 | john@example.com | | 2 | bob@example.com | +----+------------------+ 解释: john@example.com重复两次。我们保留最小的Id = 1。
解法:
1 2 3 4 5 delete p1from Person p1join Person p2on p1.email = p2.emailand p1.id > p2.id;
表: Weather
1 2 3 4 5 6 7 8 9 10 +---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | recordDate | date | | temperature | int | +---------------+---------+ id 是该表具有唯一值的列。 没有具有相同 recordDate 的不同行。 该表包含特定日期的温度信息
编写解决方案,找出与之前(昨天的)日期相比温度更高的所有日期的 id
。
返回结果 无顺序要求 。
结果格式如下例子所示。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 输入: Weather 表: +----+------------+-------------+ | id | recordDate | Temperature | +----+------------+-------------+ | 1 | 2015-01-01 | 10 | | 2 | 2015-01-02 | 25 | | 3 | 2015-01-03 | 20 | | 4 | 2015-01-04 | 30 | +----+------------+-------------+ 输出: +----+ | id | +----+ | 2 | | 4 | +----+ 解释: 2015-01-02 的温度比前一天高(10 -> 25) 2015-01-04 的温度比前一天高(20 -> 30)
解法:
1 2 3 4 select distinct w.id from Weather wjoin Weather w2on w.recordDate = Date_add(w2.recordDate, Interval 1 day )where w.temperature > w2.temperature
患者信息表: Patients
1 2 3 4 5 6 7 8 9 10 +--------------+---------+ | Column Name | Type | +--------------+---------+ | patient_id | int | | patient_name | varchar | | conditions | varchar | +--------------+---------+ 在 SQL 中,patient_id (患者 ID)是该表的主键。 'conditions' (疾病)包含 0 个或以上的疾病代码,以空格分隔。 这个表包含医院中患者的信息。
查询患有 I 类糖尿病的患者 ID (patient_id)、患者姓名(patient_name)以及其患有的所有疾病代码(conditions)。I 类糖尿病的代码总是包含前缀 DIAB1
。
按 任意顺序 返回结果表。
查询结果格式如下示例所示。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 输入: Patients表: +------------+--------------+--------------+ | patient_id | patient_name | conditions | +------------+--------------+--------------+ | 1 | Daniel | YFEV COUGH | | 2 | Alice | | | 3 | Bob | DIAB100 MYOP | | 4 | George | ACNE DIAB100 | | 5 | Alain | DIAB201 | +------------+--------------+--------------+ 输出: +------------+--------------+--------------+ | patient_id | patient_name | conditions | +------------+--------------+--------------+ | 3 | Bob | DIAB100 MYOP | | 4 | George | ACNE DIAB100 | +------------+--------------+--------------+ 解释:Bob 和 George 都患有代码以 DIAB1 开头的疾病。
解法:
1 2 select patient_id, patient_name, conditions from Patientswhere conditions like 'DIAB1%' or conditions like '% DIAB1%' ;
表: Accounts
1 2 3 4 5 6 7 8 +-------------+------+ | 列名 | 类型 | +-------------+------+ | account_id | int | | income | int | +-------------+------+ 在 SQL 中,account_id 是这个表的主键。 每一行都包含一个银行帐户的月收入的信息。
查询每个工资类别的银行账户数量。 工资类别如下:
"Low Salary"
:所有工资 严格低于 20000
美元。
"Average Salary"
: 包含 范围内的所有工资 [$20000, $50000]
。
"High Salary"
:所有工资 严格大于 50000
美元。
结果表 必须 包含所有三个类别。 如果某个类别中没有帐户,则报告 0
。
按 任意顺序 返回结果表。
查询结果格式如下示例。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 输入: Accounts 表: +------------+--------+ | account_id | income | +------------+--------+ | 3 | 108939 | | 2 | 12747 | | 8 | 87709 | | 6 | 91796 | +------------+--------+ 输出: +----------------+----------------+ | category | accounts_count | +----------------+----------------+ | Low Salary | 1 | | Average Salary | 0 | | High Salary | 3 | +----------------+----------------+ 解释: 低薪: 有一个账户 2. 中等薪水: 没有. 高薪: 有三个账户,他们是 3, 6和 8.
错误解法(不包含数量为 0 的类别):
1 2 3 4 5 6 7 8 9 10 11 12 select case when income < 20000 then 'Low Salary' when income between 20000 and 50000 then 'Average Salary' when income > 50000 then 'High Salary' end as category, count (* ) as accounts_count from Accounts group by case when income < 20000 then 'Low Salary' when income between 20000 and 50000 then 'Average Salary' when income > 50000 then 'High Salary' end ;
正确解法:
1 2 3 4 5 6 7 8 select 'Low Salary' category,count (* ) accounts_count from Accountswhere income< 20000 union select 'Average Salary' category,count (* ) accounts_count from Accountswhere income between 20000 and 50000 union select 'High Salary' category,count (* ) accounts_count from Accountswhere income> 50000