表:Products
+-------------+---------+ | Column Name | Type | +-------------+---------+ | product_id | int | | low_fats | enum | | recyclable | enum | +-------------+---------+ product_id: 是该表的主键(具有唯一值的列)。 low_fats: 是枚举类型,取值为以下两种 ('Y', 'N'),其中 'Y' 表示该产品是低脂产品,'N' 表示不是低脂产品。 recyclable: 是枚举类型,取值为以下两种 ('Y', 'N'),其中 'Y' 表示该产品可回收,而 'N' 表示不可回收。 编写解决方案找出既是低脂又是可回收的产品编号。返回结果无顺序要求。返回结果格式如下例所示: 示例 1: 输入: Products 表: +-------------+----------+------------+ | product_id | low_fats | recyclable | +-------------+----------+------------+ | 0 | Y | N | | 1 | Y | Y | | 2 | N | Y | | 3 | Y | Y | | 4 | N | N | +-------------+----------+------------+ 输出: +-------------+ | product_id | +-------------+ | 1 | | 3 | +-------------+ 解释: 只有产品 id 为 1 和 3 的产品,既是低脂又是可回收的产品。
sql:
SELECT
product_id
FROM
Products
WHERE
low_fats = 'Y' AND recyclable = 'Y';
注释:判断值相等用 “=” 而不是 is。
表: Customer
+-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | name | varchar | | referee_id | int | +-------------+---------+ 在 SQL 中,id 是该表的主键列。 该表的每一行表示一个客户的 id、姓名以及推荐他们的客户的 id。找出那些 没有被 id = 2的客户 推荐 的客户的姓名。以 任意顺序 返回结果表。结果格式如下所示。 示例 1:输入: 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 | +------+
sql:
SELECT
name
FROM
Customer
WHERE
referee_id != 2 OR referee_id is NULL;
注释:= 或 != 只能判断基本数据类型 is 关键字只能判断null。也可以用到 ifnull 判断null值,将其转为0。(select name from customer where ifnull(referee_id,0) !=2;)
World
表:
+-------------+---------+ | Column Name | Type | +-------------+---------+ | name | varchar | | continent | varchar | | area | int | | population | int | | gdp | bigint | +-------------+---------+ name 是该表的主键(具有唯一值的列)。这张表的每一行提供:国家名称、所属大陆、面积、人口和 GDP 值。如果一个国家满足下述两个条件之一,则认为该国是 大国 :
面积至少为 300 万平方公里(即,3000000 km2
),或者
人口至少为 2500 万(即 25000000
)
编写解决方案找出 大国 的国家名称、人口和面积。按 任意顺序 返回结果表。返回结果格式如下例所示。
示例:
输入: World 表: +-------------+-----------+---------+------------+--------------+ | name | continent | area | population | gdp | +-------------+-----------+---------+------------+--------------+ | Afghanistan | Asia | 652230 | 25500100 | 20343000000 | | Albania | Europe | 28748 | 2831741 | 12960000000 | | Algeria | Africa | 2381741 | 37100000 | 188681000000 | | Andorra | Europe | 468 | 78115 | 3712000000 | | Angola | Africa | 1246700 | 20609294 | 100990000000 | +-------------+-----------+---------+------------+--------------+ 输出: +-------------+------------+---------+ | name | population | area | +-------------+------------+---------+ | Afghanistan | 25500100 | 652230 | | Algeria | 37100000 | 2381741 | +-------------+------------+---------+
sql:
SELECT
name,population,area
FROM
World
WHERE
area >= 3000000 OR population >= 25000000;
注释:无
Views
表:
+---------------+---------+ | Column Name | Type | +---------------+---------+ | article_id | int | | author_id | int | | viewer_id | int | | view_date | date | +---------------+---------+ 此表可能会存在重复行。(换句话说,在 SQL 中这个表没有主键)此表的每一行都表示某人在某天浏览了某位作者的某篇文章。请注意,同一人的 author_id 和 viewer_id 是相同的。 请查询出所有浏览过自己文章的作者:
id
升序排列。示例 1:
输入: 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 | +------+
sql:
SELECT DISTINCT
author_id AS id
FROM
Views
WHERE
author_id = viewer_id
ORDER BY id;
注释:查询的结果要去除重复数据,DISTINCT 关键字可以去除重复行。输出的结果为id,可以采用 AS 关键字用于取别名。ORDER BY 关键字可以用来排序,默认为升序。
表:Tweets
+----------------+---------+ | Column Name | Type | +----------------+---------+ | tweet_id | int | | content | varchar | +----------------+---------+ 在 SQL 中,tweet_id 是这个表的主键。content 只包含美式键盘上的字符,不包含其它特殊字符。这个表包含某社交媒体 App 中所有的推文。
查询所有无效推文的编号(ID)。当推文内容中的字符数严格大于 15
时,该推文是无效的。以任意顺序返回结果表。查询结果格式如下所示:
示例 1:
输入: Tweets 表: +----------+----------------------------------+ | tweet_id | content | +----------+----------------------------------+ | 1 | Vote for Biden | | 2 | Let us make America great again! | +----------+----------------------------------+ 输出: +----------+ | tweet_id | +----------+ | 2 | +----------+ 解释: 推文 1 的长度 length = 14。该推文是有效的。 推文 2 的长度 length = 32。该推文是无效的。
sql:
SELECT
tweet_id
FROM
Tweets
WHERE
LENGTH(content) > 15;
注释:计算字节长度函数: LENGTH(),计算字符长度 CHAR_LENGTH() 。当有汉字时推荐使用 CHAR_LENGTH()。一个汉字等于三个字节。
Employees
表:
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | name | varchar | +---------------+---------+ 在 SQL 中,id 是这张表的主键。这张表的每一行分别代表了某公司其中一位员工的名字和 ID 。
EmployeeUNI
表:
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | unique_id | int | +---------------+---------+ 在 SQL 中,(id, unique_id) 是这张表的主键。这张表的每一行包含了该公司某位员工的 ID 和他的唯一标识码(unique ID)。 展示每位用户的 唯一标识码(unique ID );如果某位员工没有唯一标识码,使用 null 填充即可。你可以以 任意 顺序返回结果表。返回结果的格式如下例所示。
示例 1:
输入: Employees表: +----+----------+ | id | name | +----+----------+ | 1 | Alice | | 7 | Bob | | 11 | Meir | | 90 | Winston | | 3 | Jonathan | +----+----------+ EmployeeUNI表: +----+-----------+ | id | unique_id | +----+-----------+ | 3 | 1 | | 11 | 2 | | 90 | 3 | +----+-----------+ 输出: +-----------+----------+ | unique_id | name | +-----------+----------+ | null | Alice | | null | Bob | | 2 | Meir | | 3 | Winston | | 1 | Jonathan | +-----------+----------+ 解释: Alice and Bob 没有唯一标识码, 因此我们使用 null 替代。 Meir 的唯一标识码是 2 。 Winston 的唯一标识码是 3 。 Jonathan 唯一标识码是 1 。
sql:
SELECT
unique_id,name
FROM
Employees LEFT JOIN EmployeeUNI
ON
Employees.id = EmployeeUNI.id;
注释:LEFT JOIN 与 RIGHT JOIN 是 MYSQL 中表连接的方式。分别以左右表为基准返回左右表中的所有行,另一个表中没有的字段将以 NULL 填充。以 ON 关键字将两表的唯一属性进行连接。
销售表 Sales
:
+-------------+-------+ | Column Name | Type | +-------------+-------+ | sale_id | int | | product_id | int | | year | int | | quantity | int | | price | int | +-------------+-------+ (sale_id, year) 是销售表 Sales 的主键(具有唯一值的列的组合)。product_id 是关联到产品表 Product 的外键(reference 列)。 该表的每一行显示 product_id 在某一年的销售情况。注意: price 表示每单位价格。
产品表 Product
:
+--------------+---------+ | Column Name | Type | +--------------+---------+ | product_id | int | | product_name | varchar | +--------------+---------+ product_id 是表的主键(具有唯一值的列)。 该表的每一行表示每种产品的产品名称。
编写解决方案,以获取 Sales
表中所有 sale_id
对应的 product_name
以及该产品的所有 year
和 price
。返回结果表 无顺序要求 。
结果格式示例如下。
示例 1:
输入: Sales 表: +---------+------------+------+----------+-------+ | sale_id | product_id | year | quantity | price | +---------+------------+------+----------+-------+ | 1 | 100 | 2008 | 10 | 5000 | | 2 | 100 | 2009 | 12 | 5000 | | 7 | 200 | 2011 | 15 | 9000 | +---------+------------+------+----------+-------+ Product 表: +------------+--------------+ | product_id | product_name | +------------+--------------+ | 100 | Nokia | | 200 | Apple | | 300 | Samsung | +------------+--------------+ 输出: +--------------+-------+-------+ | product_name | year | price | +--------------+-------+-------+ | Nokia | 2008 | 5000 | | Nokia | 2009 | 5000 | | Apple | 2011 | 9000 | +--------------+-------+-------+
sql:
SELECT
product_name,year,price
FROM
Sales LEFT JOIN Product
ON
Sales.Product_id = Product.Product_id;
注释:同上一题
表:Visits
+-------------+---------+ | Column Name | Type | +-------------+---------+ | visit_id | int | | customer_id | int | +-------------+---------+ visit_id 是该表中具有唯一值的列。该表包含有关光临过购物中心的顾客的信息。
表:Transactions
+----------------+---------+ | Column Name | Type | +----------------+---------+ | transaction_id | int | | visit_id | int | | amount | int | +----------------+---------+ transaction_id 是该表中具有唯一值的列。此表包含 visit_id 期间进行的交易的信息。
有一些顾客可能光顾了购物中心但没有进行交易。请你编写一个解决方案,来查找这些顾客的 ID ,以及他们只光顾不交易的次数。返回以 任何顺序 排序的结果表。
返回结果格式如下例所示:
示例 1:
输入: Visits +----------+-------------+ | visit_id | customer_id | +----------+-------------+ | 1 | 23 | | 2 | 9 | | 4 | 30 | | 5 | 54 | | 6 | 96 | | 7 | 54 | | 8 | 54 | +----------+-------------+ Transactions +----------------+----------+--------+ | transaction_id | visit_id | amount | +----------------+----------+--------+ | 2 | 5 | 310 | | 3 | 5 | 300 | | 9 | 5 | 200 | | 12 | 1 | 910 | | 13 | 2 | 970 | +----------------+----------+--------+ 输出: +-------------+----------------+ | customer_id | count_no_trans | +-------------+----------------+ | 54 | 2 | | 30 | 1 | | 96 | 1 | +-------------+----------------+ 解释: ID = 23 的顾客曾经逛过一次购物中心,并在 ID = 12 的访问期间进行了一笔交易。 ID = 9 的顾客曾经逛过一次购物中心,并在 ID = 13 的访问期间进行了一笔交易。 ID = 30 的顾客曾经去过购物中心,并且没有进行任何交易。 ID = 54 的顾客三度造访了购物中心。在 2 次访问中,他们没有进行任何交易,在 1 次访问中,他们进行了 3 次交易。 ID = 96 的顾客曾经去过购物中心,并且没有进行任何交易。 如我们所见,ID 为 30 和 96 的顾客一次没有进行任何交易就去了购物中心。顾客 54 也两次访问了购物中心并且没有进行任何交易。
sql:
SELECT
v.customer_id, COUNT(v.visit_id) AS count_no_trans
FROM
Visits v
LEFT JOIN
Transactions t ON v.visit_id = t.visit_id
WHERE
t.transaction_id IS NULL
GROUP BY
v.customer_id;
执行 LEFT JOIN
后的结果:
v.visit_id | v.customer_id | t.transaction_id | t.amount |
---|---|---|---|
1 | 23 | 12 | 910 |
2 | 9 | 13 | 970 |
4 | 30 | NULL | NULL |
5 | 54 | 2 | 310 |
5 | 54 | 3 | 300 |
5 | 54 | 9 | 200 |
6 | 96 | NULL | NULL |
7 | 54 | NULL | NULL |
8 | 54 | NULL | NULL |
注释:题目需求是找出进行光顾确没有购买的顾客以及对应次数。首先将两张表通过 v.visit_id = t.visit_id 左连接可以得到那些不曾购物的 transaction_id 与 amount 为 null。然后通过条件查询出对应的 v.visit_id,最后使用 COUNT 来统计光顾没有购买的次数并用 GROUP BY 关键字进行分组。
表: Weather
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | recordDate | date | | temperature | int | +---------------+---------+ id 是该表具有唯一值的列。没有具有相同 recordDate 的不同行。该表包含特定日期的温度信息
编写解决方案,找出与之前(昨天的)日期相比温度更高的所有日期的 id
。返回结果 无顺序要求 。
结果格式如下例子所示:
示例 1:
输入: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)
sql:
SELECT
W1.id
FROM
Weather w1 JOIN Weather w2
ON
DATE_SUB(W1.recordDate,INTERVAL 1 DAY) = w2.recordDate
WHERE
w1.temperature > w2.temperature;
注释:当表需要与自身比较时,一般采用自连接方式。DATE_SUB 函数表示减,同理 DATE_ADD 表示加。 INTERVAL 是一个关键字表示相加/减多少,后面跟数量与数量定位。此 SQL 语句查询条件表示当 w1 减一天等于 w2时,查询 w1的温度大于 w2 温度的天数id。
表: Activity
+----------------+---------+ | Column Name | Type | +----------------+---------+ | machine_id | int | | process_id | int | | activity_type | enum | | timestamp | float | +----------------+---------+ 该表展示了一家工厂网站的用户活动。 (machine_id, process_id, activity_type) 是当前表的主键(具有唯一值的列的组合)。 machine_id 是一台机器的ID号。 process_id 是运行在各机器上的进程ID号。 activity_type 是枚举类型 ('start', 'end')。 timestamp 是浮点类型,代表当前时间(以秒为单位)。 'start' 代表该进程在这台机器上的开始运行时间戳 , 'end' 代表该进程在这台机器上的终止运行时间戳。 同一台机器,同一个进程都有一对开始时间戳和结束时间戳,而且开始时间戳永远在结束时间戳前面。
现在有一个工厂网站由几台机器运行,每台机器上运行着 相同数量的进程 。编写解决方案,计算每台机器各自完成一个进程任务的平均耗时。
完成一个进程任务的时间指进程的'end' 时间戳
减去 'start' 时间戳
。平均耗时通过计算每台机器上所有进程任务的总耗费时间除以机器上的总进程数量获得。
结果表必须包含machine_id(机器ID)
和对应的 average time(平均耗时) 别名 processing_time
,且四舍五入保留3位小数。以 任意顺序 返回表。具体参考例子如下。
示例 1:
输入:Activity table: +------------+------------+---------------+-----------+ | machine_id | process_id | activity_type | timestamp | +------------+------------+---------------+-----------+ | 0 | 0 | start | 0.712 | | 0 | 0 | end | 1.520 | | 0 | 1 | start | 3.140 | | 0 | 1 | end | 4.120 | | 1 | 0 | start | 0.550 | | 1 | 0 | end | 1.550 | | 1 | 1 | start | 0.430 | | 1 | 1 | end | 1.420 | | 2 | 0 | start | 4.100 | | 2 | 0 | end | 4.512 | | 2 | 1 | start | 2.500 | | 2 | 1 | end | 5.000 | +------------+------------+---------------+-----------+ 输出: +------------+-----------------+ | machine_id | processing_time | +------------+-----------------+ | 0 | 0.894 | | 1 | 0.995 | | 2 | 1.456 | +------------+-----------------+ 解释: 一共有3台机器,每台机器运行着两个进程. 机器 0 的平均耗时: ((1.520 - 0.712) + (4.120 - 3.140)) / 2 = 0.894 机器 1 的平均耗时: ((1.550 - 0.550) + (1.420 - 0.430)) / 2 = 0.995 机器 2 的平均耗时: ((4.512 - 4.100) + (5.000 - 2.500)) / 2 = 1.456
sql:
SELECT
a1.machine_id,
ROUND(AVG(a2.timestamp - a1.timestamp), 3) AS processing_time
FROM
Activity a1
JOIN
Activity a2
ON
a1.machine_id = a2.machine_id
AND a1.process_id = a2.process_id
AND a1.activity_type = 'start'
AND a2.activity_type = 'end'
GROUP BY
a1.machine_id;
注释:通过内连接筛选出每一个机器 process_id 相同时的 start 与 end 时间,然后通过 GROUP BY 关键字对机器 id 进行分组, 最后通过 AVG 关键词求得分组后的平均耗时时间再通过 ROUND 关键字进行四舍五入。(因为通过了 GROUP BY 分组所以 AVG 会求取 machine_id 相同时的所有耗时的平均数)。