SQL面试题

165 阅读3分钟

1.join连接查询

通常情况下DBA不建议使用JOIN查询,如果无法避免则首要问题就是选择合适的驱动表。

left join(左联接) :返回包括左表中的 所有记录 和右表中联结字段相等的记录 。

right join(右联接) :返回包括右表中的 所有记录 和左表中联结字段相等的记录。

inner join | join(等值连接): 只返回两个表中联结字段相等的行。

SELECT * FROM Person p1 INNER JOIN Person p2 ON p1.Email = p2.Email //等价于 SELECT * FROM Person p1, Person p2 WHERE p1.Email = p2.Email

全连接Full Join:Mysql不支持。

嵌套语句中,子查询只返回一个字段,则父查询可以如下:忽略关键字 from

SELECT IFNULL((SELECT Salary FROM Employee ORDER BY Salary desc LIMIT 1,1),NULL) AS SecondHighestSalary

UNION ALL & UNION

相同点:连接前后的select语句,其返回的字段名可以不一致但是字段个数必须一致。特例,如果返回全部字段则对应的两个表的字段个数必须一致。

不同点:UNION会自动对返回的字段进行去重。例如,返回字段Email的结果会进行去重。

1、第二高薪水

编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。

+----+--------+
| Id | Salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+
例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null+---------------------+
| SecondHighestSalary |
+---------------------+
| 200                 |
+---------------------+

Coding

解法一:

SELECT
    (SELECT DISTINCT
            Salary
        FROM
            Employee
        ORDER BY Salary DESC
        LIMIT 1 OFFSET 1) AS SecondHighestSalary
;

解法二:

SELECT
    IFNULL(
      (SELECT DISTINCT Salary
       FROM Employee
       ORDER BY Salary DESC
        LIMIT 1 OFFSET 1),
    NULL) AS SecondHighestSalary

Anaylaze

如果单单只用:

(SELECT DISTINCT
            Salary
        FROM
            Employee
        ORDER BY Salary DESC
        LIMIT 1 OFFSET 1)

则不会把结果为null的情况显示出来,所以给它外面再加一层。

2、超过经理收入的员工

Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应员工的经理的 Id。

+----+-------+--------+-----------+
| Id | Name  | Salary | ManagerId |
+----+-------+--------+-----------+
| 1  | Joe   | 70000  | 3         |
| 2  | Henry | 80000  | 4         |
| 3  | Sam   | 60000  | NULL      |
| 4  | Max   | 90000  | NULL      |
+----+-------+--------+-----------+
给定 Employee 表,编写一个 SQL 查询,该查询可以获取收入超过他们经理的员工的姓名。在上面的表格中,Joe 是唯一一个收入超过他的经理的员工。

+----------+
| Employee |
+----------+
| Joe      |
+----------+

Coding

# Write your MySQL query statement below
select e1.Name as Employee  from Employee e1
 join Employee e2 
on e1.ManagerId=e2.id and e1.Salary>e2.Salary

不能用left join 因为答案要求是确定的。

3、查找重复的电子邮箱

编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱。

示例:

+----+---------+
| Id | Email   |
+----+---------+
| 1  | a@b.com |
| 2  | c@d.com |
| 3  | a@b.com |
+----+---------+
根据以上输入,你的查询应返回以下结果:

+---------+
| Email   |
+---------+
| a@b.com |
+---------+
说明:所有电子邮箱都是小写字母。

Coding

解法一:

1. 先执行:
select Email, count(Email) as num
from Person
group by Email;
得到:
| Email   | num |
|---------|-----|
| a@b.com | 2   |
| c@d.com | 1   |
2. 总结
select Email from
(
  select Email, count(Email) as num
  from Person
  group by Email
) as statistic
where num > 1
;

解法二:

# Write your MySQL query statement below
select Email 
from Person 
group by Email 
having count(Email)>1;

4、删除重复的电子邮箱

编写一个 SQL 查询,来删除 Person 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。

+----+------------------+
| Id | Email            |
+----+------------------+
| 1  | john@example.com |
| 2  | bob@example.com  |
| 3  | john@example.com |
+----+------------------+

Id 是这个表的主键。 例如,在运行你的查询语句之后,上面的 Person 表应返回以下几行:

+----+------------------+
| Id | Email            |
+----+------------------+
| 1  | john@example.com |
| 2  | bob@example.com  |
+----+------------------+

Coding

# Write your MySQL query statement below
delete p1 from Person p1, Person p2
where p1.Email = p2.Email and p1.Id>p2.Id

5、locate

判断某个字段是否包含某个字符。大于0表示查询存在特定字符的行。等于0表示过滤掉存在特定字符的行。

SELECT * FROM csdn.ods_my_favorite_rt where source = '' and LOCATE("html",url) > 0;
SELECT * FROM csdn.ods_my_favorite_rt where source = '' and LOCATE("html",url) = 0;