MySQL练习题记录

题目来自Leetcode

627. Swap Salary

只用一个 SQL 查询,将 sex 字段反转

UPDATE salary
SET sex = CHAR ( ASCII(sex) ^ ASCII( 'm' ) ^ ASCII( 'f' ) );

UPDATE salary SET 
    sex = CASE sex 
        WHEN 'm' THEN 'f' 
        ELSE 'm' 
    END;

620. Not Boring Movies

查找 id 为奇数,并且 description 不是 boring 的电影,按 rating 降序。

SELECT * 
FROM cinema 
WHERE id & 1 = 1 AND description != 'boring' 
ORDER BY rating DESC;

或者利用mod(id, 2) = 1,mod(x, y)相当于x%y

596, Classes More Than 5 Students

查找有五名及以上 student 的 class

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

select 
    class 
from 
    (select 
        class, count(DISTINCT student) as num 
     from courses 
     group by class) as result
where 
    num >= 5
;

182, Duplicate Emails

查找重复的邮件地址

select
    Email
from
    Person
group by
    Email
having
    count(Email) > 1
;

196. Delete Duplicate Emails

删除重复的邮件地址

连接:

DELETE p1
FROM
    Person p1,
    Person p2
WHERE
    p1.Email = p2.Email
    AND p1.Id > p2.Id;
    
子查询:

DELETE
FROM
    Person
WHERE
    id NOT IN ( SELECT id FROM ( SELECT min( id ) AS id FROM Person GROUP BY email ) AS m );
应该注意的是上述解法额外嵌套了一个 SELECT 语句,如果不这么做,会出现错误:
You can't specify target table 'Person' for update in FROM clause。
以下演示了这种错误解法。
错误原因是:In MySQL, you can't modify the same table which you use in the SELECT part.
DELETE
FROM
    Person
WHERE
    id NOT IN ( SELECT min( id ) AS id FROM Person GROUP BY email );

参考:pMySQL Error 1093 - Can’t specify target table for update in FROM clause

175. Combine Two Tables

查找 FirstName, LastName, City, State 数据,而不管一个用户有没有填地址信息

select
    FirstName, LastName, City, State
from Person p
left join Address a on p.PersonId = a.PersonId;

181. Employees Earning More Than Their Managers

查找薪资大于其经理薪资的员工信息

select a.Name as Employee
from Employee a, Employee b
where a.ManagerId = b.id and a.Salary > b.Salary;

select a.Name as Employee
from Employee a join Employee b 
    on a.ManagerId = b.id and a.Salary > b.Salary;

183. Customers Who Never Order

查找没有订单的顾客信息:

子查询
select name as Customers
from Customers
where id not in
    (
        select CustomerId from Orders
    );
    
左外链接
SELECT
    C.Name AS Customers
FROM
    Customers C
    LEFT JOIN Orders O
    ON C.Id = O.CustomerId
WHERE
    O.CustomerId IS NULL;

184. Department Highest Salary

查找一个 Department 中收入最高者的信息:

select d.Name as Department,e.Name as Employee,m.Salary
from Employee e, Department d, 
    (select DepartmentId, max(Salary) as Salary from Employee group by DepartmentId) m
where e.DepartmentId = d.Id 
    and e.DepartmentId = m.DepartmentId 
    and e.Salary = m.Salary;
    
解法二:
select d.Name as Department,e.Name as Employee,Salary 
from Employee e join Department d on e.DepartmentId = d.Id
where 
    (DepartmentId, Salary) in 
    (select DepartmentId, max(Salary) from Employee group by DepartmentId);

176. Second Highest Salary

查找工资第二高的员工,没有找到返回 null。

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

select max(salary) as SecondHighestSalary
from employee
where salary < (select max(salary) from employee)

177. Nth Highest Salary

查找工资第 N 高的员工。

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
  set N = N-1;
  RETURN (
      # Write your MySQL query statement below.
      select distinct Salary from Employee order by Salary DESC LIMIT 1 OFFSET N
  );
END

197.Rising Temperature

今天比昨天暖

select Weather.Id as Id 
from Weather join Weather w 
    on datediff(Weather.RecordDate, w.RecordDate) = 1
        and Weather.Temperature > w.Temperature;

DATEDIFF() 函数返回两个日期之间的天数。
将上面and改为where效果更好。

The simplest and best way to get yesterday's date is:
SUBDATE(current_date, 1)

SELECT Weather.Id 
FROM   Weather 
       JOIN Weather AS w 
         ON w.RecordDate = SUBDATE(Weather.RecordDate, 1) 
WHERE  Weather.Temperature > w.Temperature 

Leetcode 619. Biggest Single Number

https://www.cnblogs.com/haoweizh/p/10198568.html
Table number contains many numbers in column num including duplicated ones.
Can you write a SQL query to find the biggest number, which only appears once.

+---+
|num|
+---+
| 8 |
| 8 |
| 3 |
| 3 |
| 1 |
| 4 |
| 5 |
| 6 | 
For the sample data above, your query should return 
the following result:

+---+
|num|
+---+
| 6 |

Note:
If there is no such number, just output null.

SELECT num FROM number GROUP BY num HAVING COUNT(*)=1 
ORDER BY num DESC LIMIT 1;

无法满足在没有时返回null的规定。
因此,若要输出null,需要满足两个条件,第一,select中应有聚合函数,第二,聚合函数处理的行数应为0。

select max(num) as num 
from (select num from number group by num havimg count(*) = 1)

LeetCode 613. Shortest Distance in a Line_Easy tag

Table point holds the x coordinate of some points on x-axis in a plane, which are all integers.
Write a query to find the shortest distance between two points in these points.

| x   |
|-----|
| -1  |
| 0   |
| 2   |

The shortest distance is ‘1’ obviously, which is from point ‘-1’ to ‘0’. So the output is as below:

| shortest|
|---------|
| 1       |

Note: Every point is unique, which means there is no duplicates in table point.

select min(abs(p1.x - p2.x)) as shortest 
from point p1 join point p2 on p1.x != p2.x

LeetCode610. Triangle Judgement_Easy tag

A pupil Tim gets homework to identify whether three line segments could possibly form a triangle.
However, this assignment is very heavy because there are hundreds of records to calculate.
Could you help Tim by writing a query to judge whether these three sides can form a triangle, assuming table triangle holds the length of the three sides x, y and z.

| x  | y  | z  |
|----|----|----|
| 13 | 15 | 30 |
| 10 | 20 | 15 |
For the sample data above, your query should return 
the follow result:

| x  | y  | z  | triangle |
|----|----|----|----------|
| 13 | 15 | 30 | No       |
| 10 | 20 | 15 | Yes      |
select *, 
if(x+y>z and x+z>y and y+z>x, 'Yes', 'No') as triangle 
from triangle

select x,y,z,
    case
        when x+y>z and x+z>y and y+z>x then 'Yes'
        else 'No'
    end as triangle
from triangle;

Leetcode 607. Sales Person

Given three tables: salesperson, company, orders.
Output all the names in the table salesperson, who didn’t have sales to company ‘RED’.

Table: salesperson

+----------+------+--------+-----------------+-----------+
| sales_id | name | salary | commission_rate | hire_date |
+----------+------+--------+-----------------+-----------+
|   1      | John | 100000 |     6           | 4/1/2006  |
|   2      | Amy  | 120000 |     5           | 5/1/2010  |
|   3      | Mark | 65000  |     12          | 12/25/2008|
|   4      | Pam  | 25000  |     25          | 1/1/2005  |
|   5      | Alex | 50000  |     10          | 2/3/2007  |
+----------+------+--------+-----------------+-----------+

Table: company

+---------+--------+------------+
| com_id  |  name  |    city    |
+---------+--------+------------+
|   1     |  RED   |   Boston   |
|   2     | ORANGE |   New York |
|   3     | YELLOW |   Boston   |
|   4     | GREEN  |   Austin   |
+---------+--------+------------+

Table: orders

+----------+----------+---------+----------+--------+
| order_id |  date    | com_id  | sales_id | amount |
+----------+----------+---------+----------+--------+
| 1        | 1/1/2014 |    3    |    4     | 100000 |
| 2        | 2/1/2014 |    4    |    5     | 5000   |
| 3        | 3/1/2014 |    1    |    1     | 50000  |
| 4        | 4/1/2014 |    1    |    4     | 25000  |
+----------+----------+---------+----------+--------+

结果

output

+------+
| name | 
+------+
| Amy  | 
| Mark | 
| Alex |
+------+

答案

select name from salesperson where sales_id not in(
select sales_id from orders
where com_id = (select com_id from company where name='Red'))
 
 
select name from salesperson where sales_id not in
(
select o.sales_id from orders o left join company c on o.com_id=c.com_id
where c.name='Red'
)

LeetCode 603. Consecutive Available Seats_Easy tag

Several friends at a cinema ticket office would like to reserve consecutive available seats.
Can you help to query all the consecutive available seats order by the seat_id using the following cinema table?

| seat_id | free |
|---------|------|
| 1       | 1    |
| 2       | 0    |
| 3       | 1    |
| 4       | 1    |
| 5       | 1    |
Your query should return the following result for the sample case above.
| seat_id |
|---------|
| 3       |
| 4       |
| 5       |

Note:

  • The seat_id is an auto increment int, and free is bool (‘1’ means free, and ‘0’ means occupied.).
  • Consecutive available seats are more than 2(inclusive) seats consecutively available.
SELECT DISTINCT c1.seat_id FROM cinema AS c1 JOIN cinema AS c2 
WHERE abs(c1.seat_id - c2.seat_id) = 1 
	and c1.free = 1 and c2.free = 1
order by c1.seat_id
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值