美文网首页
LeetCode MySQL刷题

LeetCode MySQL刷题

作者: 改不完bug的北极狐 | 来源:发表于2018-03-08 13:52 被阅读0次

    1. 重复数据类型

    1.1 查询重复数据

    编写一个 SQL查询 来查找名为 Person 的表中的所有重复电子邮件。
    示例:
    +----+---------+
    | Id | Email   |
    +----+---------+
    | 1  | a@b.com |
    | 2  | c@d.com |
    | 3  | a@b.com |
    +----+---------+
    根据以上输入,您的查询应返回以下结果:
    
    +---------+
    | Email   |
    +---------+
    | a@b.com |
    +---------+
    

    解题思路:

    • 通过百度查询到一下语句
    Select * From 表 Where 重复字段 In (Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1)  
    
    • 于是将语句修改成
    Select Email From Person Where Email In (Select Email From Person Group By Email Having Count(*)>1)
    
    • 结果出现两个相同记录


      image.png
    • 于是将语句前面加上Distinct,AC!!!
    Select Distinct Email From Person Where Email In (Select Email From Person Group By Email Having Count(*)>1)
    

    复盘:

    • 在写文档,准备一句一句弄懂每一个意思的时候,突然发现直接使用一下子语句就能解决问题
    Select Email From Person Group By Email Having Count(*)>1
    
    注释:
    Select Email From Person Group By Email 列出所有的Email
    Having Count(*) > 1 用于过滤Email数据中没有重复的数据
    

    拓展知识:
    MySQL之——查询重复记录、删除重复记录方法大全

    1.2 删除重复数据

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

    解题思路:

    • 根据上题很快想到了使用子语句,先查出重复值的大id,然后删除该id值对应的字段即可,语句如下
    Delete From person Where id IN(Select Max(id) From Person Group By email Having Count(*) > 1)
    
    • Unfortunately,程序报错了,说不能这么做
    [Err] 1093 - You can't specify target table 'person' for update in FROM clause
    
    • 于是,经过查询,得到了方法,先通过子集查询到id,然后加入一张临时表,再通过临时表删除数据,最终SQL语句如下
    DELETE FROM person WHERE id IN (select id from (select max(id) as id from person st GROUP BY email HAVING COUNT(*) > 1) st1)
    
    • Unfortunately again,Error,查看数据后得知,上面的语句其实只解决了,有两个重复的问题,如果3条或者更多一样的,程序其实是删除了最大Id的那条数据,再次修正
    • 哇,踩了一个大坑,我以为只写delete语句就行,结果还要再把结果select出来才行,其实我这道题,我想复杂了,只用先select min(id) as id from person group by email,然后接一个临时表,避免Mysql的错误,然后在delte就行了
    DELETE FROM person WHERE id NOT IN (Select id From (Select Min(id) As id From person st GROUP BY email) st1); 
    Select * From person;
    

    拓展知识:
    mysql中You can't specify target table for update in FROM clause错误

    • 自己写一个,一遍后面又不会了,内层相当于将待查询出来的数据查不来,然后外层套一个临时表,避免报1093错误(这个错误仅在MYSQL中存在,在SQL Sever和Oracle中并不存在)
    SELECT 字段 FROM (SELCT 字段 FROM 表 别名 WHER 条件) 别名
    

    2. IF类型

    2.1 更新数据中使用IF

    给定一个工资表,如下所示,m=男性 和 f=女性 。交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然)。要求使用一个更新查询,并且没有中间临时表。
    例如:
    | 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    |
    

    解题思路:

    • 这道题其实很简单,关键是使用IF语句,其语法为
    if(字段=值,真的返回值,假的返回值)
    
    • 因此答案为
    update salary set sex = if(sex='m', 'f', 'm')
    

    3. WHEN类型

    3.1 查询数据中数据WHEN

    小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id。其中纵列的 id 是连续递增的,小美想改变相邻俩学生的座位。你能不能帮她写一个 SQL query 来输出小美想要的结果呢?
    示例:
    +---------+---------+
    |    id   | student |
    +---------+---------+
    |    1    | Abbot   |
    |    2    | Doris   |
    |    3    | Emerson |
    |    4    | Green   |
    |    5    | Jeames  |
    +---------+---------+
    假如数据输入的是上表,则输出结果如下:
    +---------+---------+
    |    id   | student |
    +---------+---------+
    |    1    | Doris   |
    |    2    | Abbot   |
    |    3    | Green   |
    |    4    | Emerson |
    |    5    | Jeames  |
    +---------+---------+
    注意:如果学生人数是奇数,则不需要改变最后一个同学的座位。
    

    解题思路:

    • 此题咋一看还挺复杂的,后面经过查询发现了when case then end方法后,但最后一个奇数问题还挺困扰的,无意之间发现,在判定奇偶数的时候,也可以同时在奇数是判定下id是否为全表中最大的id,如果为最大的id,且不交换,子语句如下
    when mod(id, 2) =1 and id != (select max(id) from seat) then id -1
    
    • 故此题整体思路为,先判定id数奇偶,若为奇数且不是最大的id,则id-1,若为偶数则id+1
    select case 
    when mod (id, 2) = 1 and id != (select max(id) from seat ) then id + 1
    when mod(id, 2) = 0 then id - 1
    else id
    end id, student
    from seat
    order by id
    

    4. 常用函数类型

    4.1 Mod取余函数

    某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 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     |
    +---------+-----------+--------------+-----------+
    

    解题思路:

    • 刷了几道题,终于一个自己会写的了,仅使用了where条件判断,然后order by排序一下就行。终于一遍AC,funny
    select id, movie, description, rating from cinema
    where description != 'boring' and mod(id, 2) = 1
    order by rating desc
    

    4.1 TO_DAYS函数(将日期转换成天数的时间戳)

    Given a Weather table, write a SQL query to find all dates' Ids with higher temperature compared to its previous (yesterday's) dates.
    
    +---------+------------+------------------+
    | Id(INT) | Date(DATE) | Temperature(INT) |
    +---------+------------+------------------+
    |       1 | 2015-01-01 |               10 |
    |       2 | 2015-01-02 |               25 |
    |       3 | 2015-01-03 |               20 |
    |       4 | 2015-01-04 |               30 |
    +---------+------------+------------------+
    For example, return the following Ids for the above Weather table:
    +----+
    | Id |
    +----+
    |  2 |
    |  4 |
    +----+
    

    解题思路:

    • 该题主要是需要了解TO_DAYS()函数,解决了,当天比前一天的问题,整道题就迎刃而解了
    select w1.id from weather w1, weather w2
    where TO_DAYS(w1.date) = TO_DAYS(w2.date)+1
    and w1.temperature > w2.temperature
    

    5. 其他

    5.1

    假设一个网站包含两个表,Customers 表和 Orders 表。编写一个SQL语句找出所有从不订购任何东西的客户。
    
    表名: Customers。
    
    +----+-------+
    | Id | Name  |
    +----+-------+
    | 1  | Joe   |
    | 2  | Henry |
    | 3  | Sam   |
    | 4  | Max   |
    +----+-------+
    Table: Orders.
    
    +----+------------+
    | Id | CustomerId |
    +----+------------+
    | 1  | 3          |
    | 2  | 1          |
    +----+------------+
    以上述表格为例,返回以下内容:
    
    +-----------+
    | Customers |
    +-----------+
    | Henry     |
    | Max       |
    +-----------+
    

    答案:

    select name as Customers from customers where customers.id not in (select customerid from orders)
    

    5.1

    The Employee table holds all employees including their managers. Every employee has an Id, and there is also a column for the manager Id.
    
    +----+-------+--------+-----------+
    | Id | Name  | Salary | ManagerId |
    +----+-------+--------+-----------+
    | 1  | Joe   | 70000  | 3         |
    | 2  | Henry | 80000  | 4         |
    | 3  | Sam   | 60000  | NULL      |
    | 4  | Max   | 90000  | NULL      |
    +----+-------+--------+-----------+
    Given the Employee table, write a SQL query that finds out employees who earn more than their managers. For the above table, Joe is the only employee who earns more than his manager.
    
    +----------+
    | Employee |
    +----------+
    | Joe      |
    +----------+
    

    解题思路:

    • 我开始以为此题可能会涉及到一些子查询之类的东西,没有太多思路,后面去百度了一下,发现直接用where或者join(inner join)即可,于是以下两种方式均可
    select e.name as employee from employee e join employee m on e.ManagerId = m.Id and e.Salary > m.Salary
    select e.name from employee e, employee m WHERE e.ManagerId = m.Id and e.Salary > m.Salary
    

    相关文章

      网友评论

          本文标题:LeetCode MySQL刷题

          本文链接:https://www.haomeiwen.com/subject/ybuefftx.html