【学习】mysql学习

20190528

一、数据分析深入浅出

数据分析 深入浅出.png

二、mysql必知必会

mysql 必知必会.png

三、leecode题库

刷leecode数据库题,涉及的函数。
1、IFNULL函数:MySQL控制流函数之一,它接受两个参数,如果不是NULL,则返回第一个参数。 否则,IFNULL函数返回第二个参数,两个参数可以是文字值或表达式。
如题:
编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+

Select
    IFNULL(
      (Select DISTINCT Salary
       from Employee
       ORDER BY Salary DESC
        LIMIT 1 OFFSET 1),
    NULL) AS SecondHighestSalary;

2、聚集函数不能直接用in匹配
问题:来删除 Person 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小的那个
错误写法:

delete from person where id not in (select min(id) id from person group by email);

正确写法:

delete from person where id not in (select id from(select min(id) id from person group by email)t);

3、计算连续出现数字的问题
问题:编写一个 SQL 查询,查找所有至少连续出现三次的数字。
标准答案:

select distinct l.Num as 'ConsecutiveNums' from logs l,logs l1,logs l2 where l.Id=l1.Id-1 and l.Id=l2.Id-2 and l.Num=l1.Num and l.Num=l2.Num

还有种更复杂的联结方式

select  distinct(logs.num)as ConsecutiveNums from logs,(select (id-1)id,num from logs)a,(select (id-2)id,num from logs)b where logs.id=a.id and a.id=b.id and logs.num=a.num and a.num=b.num;

4、case+when的多级嵌套问题
问题:小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id。其中纵列的 id 是连续递增的。小美想改变相邻俩学生的座位。你能不能帮她写一个 SQL query 来输出小美想要的结果呢?
标准答案(直接不进行多级嵌套,而是序列判断):

SELECT (CASE 
            WHEN MOD(id,2) = 1 AND id = (SELECT COUNT(*) FROM seat) THEN id
            WHEN MOD(id,2) = 1 THEN id+1
            ElSE id-1
        END) AS id, student
FROM seat
ORDER BY id;

错误答案(想使用多重嵌套,但是嵌套格式不完整),无法执行:

select (case 
        when (id mod 2)=1 and id=(select count(*) from seat ) then id
        else  when (id mod 2)=1 then id+1
                 else id-1 end)
        end
             )id,student from seat order by id

错误答案修正:

select (case 
        when (id mod 2)=1 and id=(select count(*) from seat ) then id
        else    (case when (id mod 2)=1 then id+1
                             else id-1 end)
        end
             )id,student from seat order by id

20190517
开始练习MySql经典50,有一些之前没涉及的函数,做一些笔记记录。

1、有这样一组数据:('01','A'),('01','B'),('02','B'),('02','C'),如何返回字母序列为{A,B}的序列号。

方法:限定数据域处在目标阈中+数据域数目和目标阈一致


create table AA(num varchar(6),aname varchar(6));

insert into AA(num,aname) values ('01','A'),('01','B'),('02','B'),('02','C');

select * from AA;

select AA.num from AA where AA.aname in ('A','B') group by AA.num having count(*)=2;

2、mysql的rank排序。
方法:
A:不可以用rank函数:
赋值排序

select student.*, (@a:=@a+1) from student, (select @a:=0) a;
image.png

按sname列排序(先内部排序+赋值排序)

select stt.*,(@a:=@a+1) as rankname 
from (select student.* from student order by sname)stt,(select @a:=0) 
image.png

普通rank:
思路1:score 然后进行用(@rank:=@rank+1)进行排序,再group by score 取min(rank),再联立
思路2:a 表 left join a',要求排序项a<a',再group by并进行count(*)计数,再将非1的count值加上1 即为排名。

dense_rank排序:
思路1:distinct score 然后进行用(@rank:=@rank+1)进行排序,再联立

partition by排序:
思路1:先分组,再排序,再union一起;
思路2:自联结a和a',联结条件是组类一致并且排序项a<=a',再group by 排序项,并且count计算排序项的数目即为排名(但这个也只适用普通rank)。

B:可以用rank函数:
按sname列排序

select  student.*,rank() over (order by Sname) st_rank from student;
image.png

按sid,sname分组,组内按sname排序

select  student.*,rank() over (partition by sid,sname order by Sname) st_rank from student;
image.png

C:涉及到排序,但是不用返回具体排名的问题:
若不能用rank函数,能用limit解决,尽量用limit解决,不用先计算排名,如以下问题:
Employee 表包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id 。
+----+-------+--------+--------------+
| Id | Name | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1 | Joe | 70000 | 1 |
| 2 | Henry | 80000 | 2 |
| 3 | Sam | 60000 | 2 |
| 4 | Max | 90000 | 1 |
| 5 | Janet | 69000 | 1 |
| 6 | Randy | 85000 | 1 |
+----+-------+--------+--------------+
Department 表包含公司所有部门的信息。
+----+----------+
| Id | Name |
+----+----------+
| 1 | IT |
| 2 | Sales |
+----+----------+
编写一个 SQL 查询,找出每个部门工资前三高的员工。

select d.name as Department,e.name as Employee,e.Salary 
from employee e,department d
where e.departmentid=d.id 
and ((e.departmentid,e.salary) in 
(select * from(select distinct departmentid,salary from employee where departmentid=1 order by salary desc limit 3)a) 
or
 (e.departmentid,e.salary) in (select * from(select distinct departmentid,salary from employee where departmentid=2 order by salary desc limit 3)b)
)
order by Department asc,salary desc;

或者自联结的方法(以下这种方法不用管部门到底有多少数目,因此不会有很多个or出现)

select d.name as Department,
       e.name as Employee,
       e.Salary 
from employee e 
inner join department d 
on e.departmentid=d.id 
left join employee as e1 
on e.departmentid=e1.departmentid and e.salary<e1.salary 
group by e.departmentid,e.id 
having count(DISTINCT(e1.Salary))<3
order by e.departmentid asc,e.salary desc;

3、null值排序问题
null值排序默认第一,所以针对有null值的列进行排序,需要先排序再联结(left join 保留null值)。
先联结再排序:

select *, rank()over(partition by cid01.cid order by cid01.score desc)rank01 
from student 
left join 
(select * from sc where sc.cid='01')cid01 on student.sid=cid01.sid;
image.png

先排序再联结:

select student.*,cid01.rank01
from student
left join
(select sc.sid,rank()over(partition by sc.cid order by sc.score desc)rank01 from sc where sc.cid='01')cid01
on student.sid=cid01.sid;
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容