leetcode 刷题笔记(简单)

一、第二高的薪水

方法一:使用子查询和 LIMIT 子句算法

将不同的薪资按降序排序,然后使用 LIMIT 子句获得第二高的薪资。

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

然而,如果没有这样的第二最高工资,这个解决方案将被判断为 “错误答案”,因为本表可能只有一项记录。为了克服这个问题,我们可以将其作为临时表。

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

为什么使用临时表能解决null值问题?

select NULL
#返回null值

方法二:使用 IFNULL 和 LIMIT 子句
解决 “NULL” 问题的另一种方法是使用 “IFNULL” 函数,如下所示。

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

IFNULL(expr1,expr2)的用法:

假如expr1 不为 NULL,则 IFNULL() 的返回值为 expr1; 否则其返回值为 expr2

方法三:第二大的值为<最大值

select max(Salary) SecondHighestSalary 
from Employee
where Salary < (select max(Salary) from Employee)

二、超过经理收入的员工

select e2.Name Employee
from Employee e1 left join Employee e2
on e1.Id = e2.ManagerId
where e1.Salary < e2. Salary

三、查找重复的电子邮箱

解法1:(自连接之后去除重复id用where筛选)

select distinct a.Email
from Person a inner join Person b
on a.Email = b.Email 
where a.Id != b.Id

解法2:

select email from person group by email having count(email)>1

sql优化——count(1)、count(*)与count(列名)的区别

解法3:

select email 
from(select count(1) as t,email 
    from person 
    group by email) r
where r.t>1;

四、从不订购的客户

解法一:连接,用is null 判断空值

select c.Name Customers
from Orders o right join Customers c
on o.CustomerId = c.Id
where o.Id is null;

解法二:用not in

select c.Name as Customers 
from Customers c 
where c.Id not in (select distinct o.CustomerId 
                    from Orders o);

解法三:用exists
exists用法解释

select c.Name as Customers
from Customers c 
where not exists (select 1 from Orders o 
                    where o.CustomerId = c.Id);

五、删除重复的电子邮箱

删除 Person 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。
思路:删除重复的电子邮箱,并保存id最小的那个, from person p1,person p2 相当于两个person表, 当p1中的email与p2表中的email相等并且p1.Id>p2.Id 那么删除p1表中的这条重复的email保留id最小的那个email信息

delete 
  p1
 from person p1,
 person p2
 where
 p1.Email = p2.Email
 and 
 p1.Id > p2.Id

六、上升的温度

来查找与之前(昨天的)日期相比温度更高的所有日期的 id 。返回结果不要求顺序 。

SELECT DATEDIFF('2008-12-30','2008-12-29') AS DiffDate 结果为1;
SELECT DATEDIFF('2008-12-29','2008-12-30') AS DiffDate 结果为-1。

解法一:使用datediff

select a.Id 
from  Weather as a join Weather as b 
on dateDiff(a.RecordDate,b.RecordDate) = 1
and a.Temperature > b.Temperature

解法二:
mysql 中 DATE_ADD函数和 DATE_SUB函数用法

select w1.id id 
from Weather w1 
left join Weather w2
on w1.recordDate = date_add(w2.recordDate, interval 1 day) 
where w1.Temperature > w2.Temperature 

七、超过5名学生的课

注意有同学是重修

select class
from courses
group by class
having count(distinct student) >= 5

八、有趣的电影

找出所有影片描述为非 boring (不无聊) 的并且 id 为奇数 的影片,结果请按等级 rating 排列。

select 
    id 
    ,movie
    ,description
    ,rating
from cinema 
where not description = 'boring' 
and id % 2 = 1 
order by rating desc

奇数:
id % 2 = 1
mod(id,2)=1
位运算:id & 1
位运算技巧总结

九、变更性别

给定一个 salary 表,如下所示,有 m = 男性 和 f = 女性 的值。交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然)。要求只使用一个更新(Update)语句,并且没有中间的临时表。

注意,您必只能写一个 Update 语句,请不要编写任何 Select 语句。

解法一:用case when

update salary
set sex = (
    case sex when 'm' then 'f' else 'm' end

解法二:用if

update salary set sex = if(sex='m','f','m');

十、重新格式化部门表

编写一个 SQL 查询来重新格式化表,使得新的表中有一个部门 id 列和一些对应 每个月 的收入(revenue)列。

查询结果格式如下面的示例所示:

Department 表:
±-----±--------±------+
| id | revenue | month |
±-----±--------±------+
| 1 | 8000 | Jan |
| 2 | 9000 | Jan |
| 3 | 10000 | Feb |
| 1 | 7000 | Feb |
| 1 | 6000 | Mar |
±-----±--------±------+

查询得到的结果表:
±-----±------------±------------±------------±----±------------+
| id | Jan_Revenue | Feb_Revenue | Mar_Revenue | … | Dec_Revenue |
±-----±------------±------------±------------±----±------------+
| 1 | 8000 | 7000 | 6000 | … | null |
| 2 | 9000 | null | null | … | null |
| 3 | null | 10000 | null | … | null |
±-----±------------±------------±------------±----±------------+

解法一:用case when

select 
     id
    , sum(case `month` when 'Jan' then revenue else null end) as Jan_Revenue
    , sum(case `month` when 'Feb' then revenue else null end) as Feb_Revenue
    , sum(case `month` when 'Mar' then revenue else null end) as Mar_Revenue
    , sum(case `month` when 'Apr' then revenue else null end) as Apr_Revenue
    , sum(case `month` when 'May' then revenue else null end) as May_Revenue
    , sum(case `month` when 'Jun' then revenue else null end) as Jun_Revenue
    , sum(case `month` when 'Jul' then revenue else null end) as Jul_Revenue
    , sum(case `month` when 'Aug' then revenue else null end) as Aug_Revenue
    , sum(case `month` when 'Sep' then revenue else null end) as Sep_Revenue
    , sum(case `month` when 'Oct' then revenue else null end) as Oct_Revenue
    , sum(case `month` when 'Nov' then revenue else null end) as Nov_Revenue
    , sum(case `month` when 'Dec' then revenue else null end) as Dec_Revenue
from Department group by id

解法二:用if

select distinct id,
    sum(IF(month="Jan",revenue,null)) as Jan_Revenue,
    sum(IF(month="Feb",revenue,null)) as Feb_Revenue,
    sum(IF(month="Mar",revenue,null)) as Mar_Revenue,
    sum(IF(month="Apr",revenue,null)) as Apr_Revenue,
    sum(IF(month="May",revenue,null)) as May_Revenue,
    sum(IF(month="Jun",revenue,null)) as Jun_Revenue,
    sum(IF(month="Jul",revenue,null)) as Jul_Revenue,
    sum(IF(month="Aug",revenue,null)) as Aug_Revenue,
    sum(IF(month="Sep",revenue,null)) as Sep_Revenue,
    sum(IF(month="Oct",revenue,null)) as Oct_Revenue,
    sum(IF(month="Nov",revenue,null)) as Nov_Revenue,
    sum(IF(month="Dec",revenue,null)) as Dec_Revenue
    from Department group by id order by id;

注:单独地使用group by (不加聚合函数),只能显示出每组记录的第一条记录。但凡使用group by,前面一定要有聚合函数(MAX /MIN / SUM /AVG / COUNT)

参考:group by的使用

所有资料来源均来源于网络,本文章仅用于个人学习整理。

上一篇:mysql出1075-Incorrect table definition;


下一篇:NetSuite Batch Process Status