一、丢失信息的雇员
题目描述:
表: Employees +-------------+---------+ | Column Name | Type | +-------------+---------+ | employee_id | int | | name | varchar | +-------------+---------+ employee_id 是这个表的主键。 每一行表示雇员的id 和他的姓名。 表: Salaries +-------------+---------+ | Column Name | Type | +-------------+---------+ | employee_id | int | | salary | int | +-------------+---------+ employee_id is 这个表的主键。 每一行表示雇员的id 和他的薪水。 写出一个查询语句,找到所有丢失信息的雇员id。当满足下面一个条件时,就被认为是雇员的信息丢失: 雇员的姓名丢失了,或者 雇员的 薪水信息 丢失了,或者 返回这些雇员的id employee_id , 从小到大排序 。 查询结果格式如下面的例子所示。 示例 1: 输入: Employees table: +-------------+----------+ | employee_id | name | +-------------+----------+ | 2 | Crew | | 4 | Haven | | 5 | Kristian | +-------------+----------+ Salaries table: +-------------+--------+ | employee_id | salary | +-------------+--------+ | 5 | 76071 | | 1 | 22517 | | 4 | 63539 | +-------------+--------+ 输出: +-------------+ | employee_id | +-------------+ | 1 | | 2 | +-------------+ 解释: 雇员1,2,4,5 都工作在这个公司。 1号雇员的姓名丢失了。 2号雇员的薪水信息丢失了。
代码详解:
# 雇员的姓名丢失了或者雇员的薪水信息丢失,都会导致employee_id # 在 employees 和salaries 的并集表里面仅出现一次 select employee_id from ( select employee_id from employees union all select employee_id from salaries) as t group by employee_id having count(employee_id) = 1 order by employee_id;
二、每个产品在不同商店的价格
题目描述:
表:Products +-------------+---------+ | Column Name | Type | +-------------+---------+ | product_id | int | | store1 | int | | store2 | int | | store3 | int | +-------------+---------+ 这张表的主键是product_id(产品Id)。 每行存储了这一产品在不同商店store1, store2, store3的价格。 如果这一产品在商店里没有出售,则值将为null。 请你重构 Products 表,查询每个产品在不同商店的价格,使得输出的格式变为(product_id, store, price) 。 如果这一产品在商店里没有出售,则不输出这一行。 输出结果表中的 顺序不作要求 。 查询输出格式请参考下面示例。 示例 1: 输入: Products table: +------------+--------+--------+--------+ | product_id | store1 | store2 | store3 | +------------+--------+--------+--------+ | 0 | 95 | 100 | 105 | | 1 | 70 | null | 80 | +------------+--------+--------+--------+ 输出: +------------+--------+-------+ | product_id | store | price | +------------+--------+-------+ | 0 | store1 | 95 | | 0 | store2 | 100 | | 0 | store3 | 105 | | 1 | store1 | 70 | | 1 | store3 | 80 | +------------+--------+-------+ 解释: 产品0在store1,store2,store3的价格分别为95,100,105。 产品1在store1,store3的价格分别为70,80。在store2无法买到。
代码详解:
# 一列一列处理:把“列名”做为新列的value(如本题的store),把原来的value也作为新列(如本题的price),这是一个查询,其他列不要 # 用union all拼接每一列的结果 # 本题如果这一产品在商店里没有出售,则不输出这一行,所以要原列 is not null的筛选条件 select product_id, 'store1' as store, store1 as price from Products where store1 is not null union all select product_id, 'store2' as store, store2 as price from Products where store2 is not null union all select product_id, 'store3' as store, store3 as price from Products where store3 is not null;
三、树节点
题目描述:
给定一个表 tree,id 是树节点的编号, p_id 是它父节点的 id 。 +----+------+ | id | p_id | +----+------+ | 1 | null | | 2 | 1 | | 3 | 1 | | 4 | 2 | | 5 | 2 | +----+------+ 树中每个节点属于以下三种类型之一: 叶子:如果这个节点没有任何孩子节点。 根:如果这个节点是整棵树的根,即没有父节点。 内部节点:如果这个节点既不是叶子节点也不是根节点。 写一个查询语句,输出所有节点的编号和节点的类型,并将结果按照节点编号排序。上面样例的结果为: +----+------+ | id | Type | +----+------+ | 1 | Root | | 2 | Inner| | 3 | Leaf | | 4 | Leaf | | 5 | Leaf | +----+------+ 解释: 节点 '1' 是根节点,因为它的父节点是 NULL ,同时它有孩子节点 '2' 和 '3' 。 节点 '2' 是内部节点,因为它有父节点 '1' ,也有孩子节点 '4' 和 '5' 。 节点 '3', '4' 和 '5' 都是叶子节点,因为它们都有父节点同时没有孩子节点。 样例中树的形态如下: 1 / \ 2 3 / \ 4 5 注意: 如果树中只有一个节点,你只需要输出它的根属性。
代码详解:
# 使用CASE WHEN select id, case when p_id is null then 'Root' when id in (select distinct p_id from tree) then 'Inner' else 'Leaf' end as type from tree;
四、第二高的薪水
题目描述:
Employee 表: +-------------+------+ | Column Name | Type | +-------------+------+ | id | int | | salary | int | +-------------+------+ id 是这个表的主键。 表的每一行包含员工的工资信息。 编写一个 SQL 查询,获取并返回 Employee 表中第二高的薪水 。如果不存在第二高的薪水,查询应该返回 null 。 查询结果如下例所示。 示例 1: 输入: Employee 表: +----+--------+ | id | salary | +----+--------+ | 1 | 100 | | 2 | 200 | | 3 | 300 | +----+--------+ 输出: +---------------------+ | SecondHighestSalary | +---------------------+ | 200 | +---------------------+ 示例 2: 输入: Employee 表: +----+--------+ | id | salary | +----+--------+ | 1 | 100 | +----+--------+ 输出: +---------------------+ | SecondHighestSalary | +---------------------+ | null | +---------------------+
代码详解:
# 将不同的薪资按降序排序,然后使用 LIMIT 子句获得第二高的薪资。 # ifnull(x,y):如果x不为null,则函数值为x,否则为y select ifnull( (select distinct Salary from Employee order by Salary desc limit 1 OFFSET 1), NULL) as SecondHighestSalary;