LeetCode 数据库练习笔记

175. 组合两表
    左查询: left join ... on ...
    
176. 第二高的薪水 如果不存在第二高的薪水,则返回null  (考察 ifnull 和 limit/offset)
    DISTINCT: 去重
    SQL查询语句中的 limit 与 offset 的区别:
    limit y 分句表示: 读取 y 条数据
    limit x, y 分句表示: 跳过 x 条数据,读取 y 条数据
    limit y offset x 分句表示: 跳过 x 条数据,读取 y 条数据
    
    查询第N高数据?
    题解一:  查询出最高的数据,在此前提上,再查出最高的数据
    题解二:  使用limit和offset 查询
    
    ifnull:
    select ifnull(
     (select distinct Salary from Employee order by Salary  desc limit 1,1),null)
     as "SecondHighestSalary";
     
     窗口函数:
     select distinct Salary from
        (
            select Salary,dense_rank() over(order by Salary desc) rnk from Employee
        ) t where rnk=@N
     
     

181.超过经理收入的员工  (考察 内连接)

    Employee表
    +----+-------+--------+-----------+
    | Id | Name  | Salary | ManagerId |
    +----+-------+--------+-----------+
    | 1  | Joe   | 70000  | 3         |
    | 2  | Henry | 80000  | 4         |
    | 3  | Sam   | 60000  | NULL      |
    | 4  | Max   | 90000  | NULL      |
    +----+-------+--------+-----------+
    
    预期效果
    +----------+
    | Employee |
    +----------+
    | Joe      |
    +----------+

    # Write your MySQL query statement below
    # 子查询
    #select Name as Employee from Employee a 
    # where Salary >(Select Salary from Employee where Id = a.ManagerId);
    #使用where语句  会产生笛卡尔积 不推荐使用  消耗内存比较大 
    #select a.Name as 'Employee'
    #from Employee a , Employee b 
    #where a.ManagerId = b.Id
    #and a.Salary > b.Salary;
    #使用join 方法  优化
    select a.Name as 'Employee'
    from Employee a join Employee b 
    on a.ManagerId = b.Id
    and a.Salary > b.Salary;
    
182. 查找重复的电子邮箱 (考察 group by)    优先级顺序:where>group by>having>order by
    person表
    +----+---------+
    | Id | Email   |
    +----+---------+
    | 1  | [email protected] |
    | 2  | [email protected] |
    | 3  | [email protected] |
    +----+---------+
    预期效果
    +---------+
    | Email   |
    +---------+
    | [email protected] |
    +---------+
    
    # Write your MySQL query statement below
    # 自连接   表数据庞大的时候 查询相对慢
    #select distinct p1.Email Email 
    #from Person  p1 join Person p2
    #on p1.Email = p2.Email; 

    # group by  having
    #select Email from Person group by Email having count(Email)>1;
    # group by 和 临时表
    select Email  from (select Email ,count(Email) as num from Person group by Email) as NemPerson   where num > 1;
    
    
    
    
183. 从不订购的客户  (考察: not in )
    Customers 表:

    +----+-------+
    | Id | Name  |
    +----+-------+
    | 1  | Joe   |
    | 2  | Henry |
    | 3  | Sam   |
    | 4  | Max   |
    +----+-------+
    Orders 表:

    +----+------------+
    | Id | CustomerId |
    +----+------------+
    | 1  | 3          |
    | 2  | 1          |
    +----+------------+
    例如给定上述表格,你的查询应返回:
    
    +-----------+
    | Customers |
    +-----------+
    | Henry     |
    | Max       |
    +-----------+

    # Write your MySQL query statement below
    #自连接  80 ms 一般解
    #select c.Name Customers  from Customers c left join 
    #(select CustomerId , count(CustomerId) as num from Orders group by CustomerId)
    #as o 
    #on c.Id = o.CustomerId
    #where o.num is null;
    #  优质解
    #select c.Name Customers from Customers c left join Orders o  on c.Id = o.CustomerId #where o.CustomerId is null;
    #官方解  最优解
    select customers.name Customers from customers
     where customers.id not in 
     (
         select CustomerId from Orders
     );
     
196. 删除重复的电子邮箱 (考察 Delete  Delete和 自连接 left/right join ... on ...不能同时使用  常与where 使用 )
    编写一个 SQL 查询,来删除 Person 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。

    +----+------------------+
    | Id | Email            |
    +----+------------------+
    | 1  | [email protected] |
    | 2  | [email protected]  |
    | 3  | [email protected] |
    +----+------------------+
    Id 是这个表的主键
    例如,在运行你的查询语句之后,上面的 Person 表应返回以下几行:

    +----+------------------+
    | Id | Email            |
    +----+------------------+
    | 1  | [email protected] |
    | 2  | [email protected]  |
    +----+------------------+
    
    # Write your MySQL query statement below
    #delete p1 from Person p1 , Person p2 where p1.Email = p2.Email and p1.Id > p2.Id;

    #1.找出要删除的重复数据
    #select distinct p.Id as id from person p , person s where p.Email = s.Email and p.Id>s.Id;
    #2.MySQL不允许select 和 delete 操作同一个表
    #select id from (select distinct p.Id as id from person p , person s where p.Email = s.Email and p.Id>s.Id) as tmp;
    #3.删除重复数据
    delete from person where id in ( select id from (select distinct p.Id as id from person p , person s where p.Email = s.Email and p.Id>s.Id) as tmp);
    #91ms 没有考虑去重
    #delete  p1 from person p1, person p2 where p1.Email = p2.Email and  p1.Id > p2.Id;
    
197.上升的温度    ( DATEDIFF() 函数计算两个日期之间的间隔天数 )
    给定一个 Weather 表,编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id。

    +---------+------------------+------------------+
    | Id(INT) | RecordDate(DATE) | Temperature(INT) |
    +---------+------------------+------------------+
    |       1 |       2015-01-01 |               10 |
    |       2 |       2015-01-02 |               25 |
    |       3 |       2015-01-03 |               20 |
    |       4 |       2015-01-04 |               30 |
    +---------+------------------+------------------+
    例如,根据上述给定的 Weather 表格,返回如下 Id:

    +----+
    | Id |
    +----+
    |  2 |
    |  4 |
    +----+
    
    # Write your MySQL query statement below
    #select w1.Id from Weather w1,Weather w2 where w1.Temperature > w2.Temperature and datediff(w1.RecordDate,w2.RecordDate)=1;
    
595. 大的国家 (考察:or 的使用方法 另外的解法 :union /union all UNION 操作符用于合并两个或多个 SELECT 语句的结果集。)
    这里有张 World 表
    +-----------------+------------+------------+--------------+---------------+
    | name            | continent  | area       | population   | gdp           |
    +-----------------+------------+------------+--------------+---------------+
    | Afghanistan     | Asia       | 652230     | 25500100     | 20343000      |
    | Albania         | Europe     | 28748      | 2831741      | 12960000      |
    | Algeria         | Africa     | 2381741    | 37100000     | 188681000     |
    | Andorra         | Europe     | 468        | 78115        | 3712000       |
    | Angola          | Africa     | 1246700    | 20609294     | 100990000     |
    +-----------------+------------+------------+--------------+---------------+
    如果一个国家的面积超过300万平方公里,或者人口超过2500万,那么这个国家就是大国家。

    编写一个SQL查询,输出表中所有大国家的名称、人口和面积。

    例如,根据上表,我们应该输出:

    +--------------+-------------+--------------+
    | name         | population  | area         |
    +--------------+-------------+--------------+
    | Afghanistan  | 25500100    | 652230       |
    | Algeria      | 37100000    | 2381741      |
    +--------------+-------------+--------------+

    # Write your MySQL query statement below
    select name , population , area from World where area>3000000 or population >25000000;
    
    select name,population,area from World where area > 3000000 union select name,population,area from World where population > 25000000;
    
596. 超过5名学生的课    (grouo by &&  having  ||  group by  && 子查询)    where 要比 having 速度快很多
    有一个courses 表 ,有: student (学生) 和 class (课程)。

    请列出所有超过或等于5名学生的课。

    例如,表:

    +---------+------------+
    | student | class      |
    +---------+------------+
    | A       | Math       |
    | B       | English    |
    | C       | Math       |
    | D       | Biology    |
    | E       | Math       |
    | F       | Computer   |
    | G       | Math       |
    | H       | Math       |
    | I       | Math       |
    +---------+------------+
    应该输出:

    +---------+
    | class   |
    +---------+
    | Math    |
    +---------+
    Note:
    学生在每个课中不应被重复计算。
    
    # Write your MySQL query statement below
    #group by  && having    速度慢
    #select  class  from courses  group by class having count(distinct student)>=5 ;
    #group by && 子查询    where   速度快
    #select class, count(class) as num from courses group by class ;
    select class from (select class, count(distinct student) as num from courses group by class  ) as tmp where num >=5;
    
620. 有趣的电影 (考察  按顺序排列: order by  lke  not like   判断奇偶性 mod(id,2)=1;   description可用 本题效率不高)
    not like  和 !=   效率相比    !=效率要比 not like 速率高  精确查找用!=   模糊查找用 like / not like 
    某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 LED显示板做电影推荐,上面公布着影评和相关电影描述。

    作为该电影院的信息部主管,您需要编写一个 SQL查询,找出所有影片描述为非 boring (不无聊) 的并且 id 为奇数 的影片,结果请按等级 rating 排列。

    例如,下表 cinema:

    +---------+-----------+--------------+-----------+
    |   id    | movie     |  description |  rating   |
    +---------+-----------+--------------+-----------+
    |   1     | War       |   great 3D   |   8.9     |
    |   2     | Science   |   fiction    |   8.5     |
    |   3     | irish     |   boring     |   6.2     |
    |   4     | Ice song  |   Fantacy    |   8.6     |
    |   5     | House card|   Interesting|   9.1     |
    +---------+-----------+--------------+-----------+
    对于上面的例子,则正确的输出是为:

    +---------+-----------+--------------+-----------+
    |   id    | movie     |  description |  rating   |
    +---------+-----------+--------------+-----------+
    |   5     | House card|   Interesting|   9.1     |
    |   1     | War       |   great 3D   |   8.9     |
    +---------+-----------+--------------+-----------+
    
    # Write your MySQL query statement below
    #按等级排    order by   rating  desc
    #非boring   description!= boring
    #id为奇数   id%2=1        
    #select * from cinema where id % 2 and description <> 'boring' order by rating desc;
    #select id , movie , description , rating from cinema where description  not like '%boring%' and mod(id,2)=1 order by rating DESC;
    select id , movie , description , rating from cinema where description  != '%boring%' and mod(id,2)=1 order by rating DESC;
    
627. 交换工资
    给定一个 salary 表,如下所示,有 m = 男性 和 f = 女性 的值。交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然)。要求只使用一个更新(Update)语句,并且没有中间的临时表。

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

    例如:

    | id | name | sex | salary |
    |----|------|-----|--------|
    | 1  | A    | m   | 2500   |
    | 2  | B    | f   | 1500   |
    | 3  | C    | m   | 5500   |
    | 4  | D    | f   | 500    |
    运行你所编写的更新语句之后,将会得到以下表:

    | id | name | sex | salary |
    |----|------|-----|--------|
    | 1  | A    | f   | 2500   |
    | 2  | B    | m   | 1500   |
    | 3  | C    | f   | 5500   |
    | 4  | D    | m   | 500    |

    1.用if,注意中间是一个表达式 比如sex='m'
    可以使用 if 函数判断 列的值 进行数据交换 当没有where 条件的时候会更新全表
    IF 函数用法
    IF(expr,v1,v2) 如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2

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

    2.用case when
    因为本身的格式是
    update 表 set 某个值= xxx

    而case的写法
    case 某个值 when 1 then 2
    when 2 then 1
    else 3 剩下来的写3
    end

    那下面的写法如果是f 则是m
    如果是m (直接省略为else)则是f

    因为这里是动态变化所以要用case或者if来写

    update salary
    set sex=(case sex
    when 'f' then 'm'
    else 'f'
    end)
    
    # Write your MySQL query statement below
    #118 ms   91.54
    #update salary set sex = case sex when 'm' then 'f' else 'm' end;
    # 119 ms   87.75
    update salary set sex = IF(sex = 'm', 'f', 'm');
    #orcale中会用到
    #UPDATE salary SET sex = DECODE(sex,'m','f','m');

1179. 重新格式化部门表
    部门表 Department:

    +---------------+---------+
    | Column Name   | Type    |
    +---------------+---------+
    | id            | int     |
    | revenue       | int     |
    | month         | varchar |
    +---------------+---------+
    (id, month) 是表的联合主键。
    这个表格有关于每个部门每月收入的信息。
    月份(month)可以取下列值 ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]。
     

    编写一个 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        |
    +------+-------------+-------------+-------------+-----+-------------+

    注意,结果表有 13 列 (1个部门 id 列 + 12个月份的收入列)。

 

所有材料及题解来源均出于:力扣(LeetCode)
链接:https://leetcode-cn.com/problems
申明:著作权归领扣网络所有,商业转载请联系官方授权。

    


     


 

你可能感兴趣的:(java学习笔记)