mysql练习与打卡笔记


mysql的安装:
https://blog.csdn.net/submarineas/article/details/89762584 windows下mysql的安装

https://blog.csdn.net/submarineas/article/details/86532966 Linux下mysql的安装

Navicat的使用总结:
https://blog.csdn.net/submarineas/article/details/90271858
Navicat使用技巧

2019/8/5:查找重复的电子邮箱与大国

查找重复的电子邮箱

关于查找重复电子邮箱,意思很直白,什么时候可以判断为重复?当email相同或者用count统计出email数量为2即以记为重复,那么便有两种方式可以写了:

select Email from email group by Email having count(Email) >= 2

select DISTINCT A.Email from email A,email B where A.Email = B.Email and A.id != B.id

关于上面sql中having和where可以互换位置嘛,我又特意去试了一下,发现会报Group function is not allowed here,因为sql的执行顺序为from子句 ——> where 子句 ——> group by 子句 ——> having 子句 ——> order by 子句 ——> select 子句

关于select的查询操作,我之前也有总结一篇博客,只不过后来没怎么用sql了,然后到今天我重新翻看才发现还没有总结完:

mysql(3):查询基础总结

在这里插入图片描述

查找大国:

通过这句话:如果一个国家的面积超过300万平方公里,或者(人口超过2500万并且gdp超过2000万),那么这个国家就是大国家。

就可以直接写出sql了:

select name,population,area
from world
where population>25000000
or area>3000000;

在这里插入图片描述

2019/8/7:连续出现的数字与超过经理收入的员工

连续出现的数字

题目说明:
编写一个 SQL 查询,查找所有至少连续出现三次的数字。
https://leetcode-cn.com/problems/consecutive-numbers/


最简单的一种思路便是通过自身连续连表三次,和上面的电子邮件题一样,然后判断id和num,以上题email中的数据,那么我们便可以写出sql:
select distinct a.Email ConsecutiveNums 
from email a,email b,email c
where a.Email=b.Email
and b.Email=c.Email
and a.Id+1=b.Id
and b.Id+1=c.Id

另外这里的去重也可以用group by,都一样,然后我看到一种使用用户变量的方式进行判断的,感觉很强,在这里记录一下,方便之后学完变量后回看:

select distinct Num as ConsecutiveNums
from (
  select Num, 
    case 
      when @prev = Num then @count := @count + 1
      when (@prev := Num) is not null then @count := 1
    end as CNT
  from Logs, (select @prev := null,@count := null) as t
) as temp
where temp.CNT >= 3

超过经理收入的员工

Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应员工的经理的 Id。

+----+-------+--------+-----------+
| Id | Name  | Salary | ManagerId |
+----+-------+--------+-----------+
| 1  | Joe   | 70000  | 3         |
| 2  | Henry | 80000  | 4         |
| 3  | Sam   | 60000  | NULL      |
| 4  | Max   | 90000  | NULL      |
+----+-------+--------+-----------+

给定 Employee 表,编写一个 SQL 查询,该查询可以获取收入超过他们经理的员工的姓名。在上面的表格中,Joe 是唯一一个收入超过他的经理的员工。

+----------+
| Employee |
+----------+
| Joe      |
+----------+

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/employees-earning-more-than-their-managers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

然后我们便可以写出sql为:

select B.name as Employee 
from Employee A,Employee B 
where A.id = B.ManagerId 
and A.Salary < B.Salary;

在这里插入图片描述

看了下leetcode官方题解,发现还能换成join:

SELECT
     a.NAME AS Employee
FROM Employee AS a JOIN Employee AS b
     ON a.ManagerId = b.Id
     AND a.Salary > b.Salary

在这里插入图片描述

2019/8/8:超过5名学生的课与交换工资

超过5名学生的课

有一个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:学生在每个课中不应被重复计算。

开始没有看到那句note,导致忘记筛选重复值,而当进行到第四个测试用例的时候出现了报错,即当有两个A选了math的时候只能算一个,然后看到这个用例的时候,我在后面的条件中加了去重,然后可以了:

{"headers": {"courses": ["student", "class"]}, "rows": {"courses": [["A", "Math"], ["B", "English"], ["C", "Math"], ["D", "Biology"], ["E", "Math"], ["F", "Math"], ["A", "Math"]]}}

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

在这里插入图片描述
这里看到一个网友通过正向推导的三步,感觉很强,我上面是直接反向了,因为逻辑更简单,正向也不一定能推出来,所以在这里记录一下:

#共三种写法
#最朴实的写法,共三层查询,先利用 DISTINCT 去掉重复记录得到表 A,再利用 GROUP BYCLASS 分组,然
#后用 COUNT() 统计每组个数得到表 B,最后在最外层限定数量 >=5 查到结果
SELECT B.CLASS								#最外层
	FROM (SELECT A.CLASS,COUNT(A.CLASS) C          #第二层查询,得到具有 CLASSCOUNT(CLASS) 的表 B
		FROM (SELECT DISTINCT *				#第三层查询,去重得到表 A
			FROM COURSES) A
	GROUP BY A.CLASS) B						#分组
	WHERE B.C >= 5;							#条件

#稍微优化,两层查询,主要是因为用了 HAVING 省了一层查询
SELECT A.CLASS					#最外层
	FROM (SELECT DISTINCT *		#第二层查询,去重得到表 a
		FROM COURSES) A
	GROUP BY A.CLASS			        #分组
	HAVING COUNT(A.CLASS) >= 5;	#利用 COUNT() 计算每组个数并筛选

#极致优化,一层查询,利用 GROUP BYCLASS 分组后,直接用 COUNT() 统计每组学生个数,在统计前先用
#DISTINCT 去掉重复学生
SELECT CLASS
	FROM COURSES
	GROUP BY CLASS							#分组
	HAVING COUNT(DISTINCT STUDENT) >= 5;          #利用 COUNT() 统计每门课 STUDENT 的个数,同时利
                                                                                        #用 DISTINCT 去掉重复学生、

交换工资

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

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

通过注意这句话基本否定了向select想的思路,同时也减少了很多复杂的操作,我也不至于去想,那么既然要满足男性与女性交换工资,在python中通过if else进行,那么mysql中有同样操作常见的便是case when了,关于update的语法格式如下:


update table  
set 字段1=case     
    when 条件1 then 值1       
    when 条件2 then 值2      
    else3      
    end     
where    ……

update salary  
set sex=case sex   
    when "m" then "f"       
    when "f" then "m"	# 或者是else "m"
end

另外翻出我去年为了背面试题画的mysql思维导图,现在感觉接近忘了一半。。最近又要重新开始记了。

mysql总结(一):思维导图


有趣的电影

某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 LED显示板做电影推荐,上面公布着影评和相关电影描述。

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

这题讲得很通俗了,非boring、id为奇数、按rating排序(降序)。所以可以写出sql为:

select id,movie,description,rating from cinema where cinema.description != "boring" and id % 2 = 1 order by rating desc;
# 另外看到官方题解使用 MOD() 函数,感觉差不多

2019/8/9(实际是8,提前批):组合两张表和从不订购的客户

组合两张表

编写一个 SQL 查询,满足条件:无论 person 是否有地址信息,都需要基于上述两表提供 person 的以下信息:

这题考虑的是怎样选择一种连接方式使得Adress表中地址id为空时,表连接关系依然成立,可以看我最上面分享的sql查询中的一张图,我中间也忘了,然后看着这张图想起来怎么做,这里引用一下:
在这里插入图片描述

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

在这里插入图片描述

从不订购的客户

某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。

https://leetcode-cn.com/problems/customers-who-never-order/

这题就是上图的位于左中和右中的两张图,即有一边的null为空,而另一边排除掉这一部分,所以sql为:

select A.Name as Customers from Customers A left join Orders B on A.Id=B.CustomerId WHERE B.CustomerId is null;

在这里插入图片描述

删除重复的邮箱

编写一个 SQL 查询,来删除 Person 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。

https://leetcode-cn.com/problems/delete-duplicate-emails/

写了半天,发现无论怎么写都是全部的值,然后跑去看题解,发现原来这题竟然是要写删除。。。好吧,没看懂需求,卡得心累,还瞎写了半天子查询,然而没有删除的操作根本判断不了。。直接上官方题解吧:

DELETE p1 FROM Person p1,Person p2 WHERE p1.Email = p2.Email AND p1.Id > p2.Id

好像今天刷了8题,从下午3点到接近9点,6道sql和2道python,可能中途有比较急的地方,接下来还要花一段时间再过一遍了。

2019/8/9:分数排名与换座位

分数排名

编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。

链接:https://leetcode-cn.com/problems/rank-scores

这题可以按正向走或者反向走,刚开始看题没有想明白这回事,大概猜到是自连接但写了很久没写出来,然后看了下题解,发现我忽略了一点,即如果要算当前排名,那么只需要推导出比它大的非重复个数就知道它排第几了,那么sql为:

 select s.Score,(select count(distinct Score) 
    from Scores where Score>=s.Score)     # 查看当前比自己大的去重后的个数
              as Rank from Scores s 
                  order by s.Score desc

select s1.Score, count(distinct(s2.Score)) Rank
from Scores s1, Scores s2
where s1.Score<=s2.Score
group by s1.Id

如果理解了题目意思,第二句更容易写出来。

换座位

小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id。

其中纵列的 id 是连续递增的

小美想改变相邻俩学生的座位。

你能不能帮她写一个 SQL query 来输出小美想要的结果呢?

链接:https://leetcode-cn.com/problems/exchange-seats

这题概念很模糊,和上面的交换工资很类似,但这里的名字是字符串,而上面的性别可以看成是boolean布尔值,所以应该是用case when,但具体怎么写,还有特意强调id是自增的以及奇数最后一个不排,这个就不太会了,可能概念记得浅,这题甚至没敢动手,然后去看了下答案发现还行吧,理解起来也有点难度,日后回顾:

SELECT * FROM(
    SELECT id-1 AS id,student FROM seat WHERE id%2=0
    # 如果是偶数,那么id数-1,即所有偶数同学向前坐
    UNION
    SELECT id+1 AS id,student FROM seat WHERE id%2=1 AND (id+1) <= (SELECT COUNT(*) FROM seat)
    # 当id数是奇数且不大于且id数加一不大于总座位数时,将id数+1,学生向后坐
    UNION
    SELECT id AS id,student FROM seat WHERE id%2=1 AND (id+1) > (SELECT COUNT(*) FROM seat)		
    # 当id数是奇数且id数加一大于总座位数时,id数不变。没有多余位子换了,这个学生不动
) AS T1
ORDER BY id ASC

2019/8/10:部门工资最高的员工与部门工资前三高的所有员工

部门工资最高的员工

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            |
+----+-------+--------+--------------+

Department 表包含公司所有部门的信息。

+----+----------+
| Id | Name     |
+----+----------+
| 1  | IT       |
| 2  | Sales    |
+----+----------+

编写一个 SQL 查询,找出每个部门工资最高的员工。例如,根据上述给定的表格,Max 在 IT 部门有最高工资,Henry 在 Sales 部门有最高工资。

+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT         | Max      | 90000  |
| Sales      | Henry    | 80000  |
+------------+----------+--------+

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/department-highest-salary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


前面都能写出来,都是常见的套路,但在建立第三张表的时候,没有建立出来,应该说是迟疑了,或者说当时脑子里思绪是不用这么麻烦?还是练得太少,一多想,思路就会变得杂乱无章,另外看了下官方题解,发现确实不用第三张表也行,然而我就不太理解in的用法了,可能我用的太少,它的这种用法确实巧妙:

select 
B.Name as Department,
A.Name as Employee,
C.max_salary as Salary
from Employee A,Department B,
(select DepartmentId,MAX(Salary) as max_salary from Employee C group by DepartmentId) as C
where A.DepartmentId = B.Id and A.Salary = C.max_salary and A.DepartmentId = C.DepartmentId

上述是看了一些题解,我发现还是这种比较好理解一些,所以就自己再写了一遍,最后一定不要忘了还有一个条件,就是A.DepartmentId = C.DepartmentId,否则结果会出现Employee 表的笛卡尔积。

然后官方给的题解我觉得不是很好理解,可能我还是对sql语法有些不熟,在这里记录一下:

SELECT
    Department.name AS 'Department',
    Employee.name AS 'Employee',
    Salary
FROM
    Employee
        JOIN
    Department ON Employee.DepartmentId = Department.Id
WHERE
    (Employee.DepartmentId , Salary) IN
    (   SELECT
            DepartmentId, MAX(Salary)
        FROM
            Employee
        GROUP BY DepartmentId
	)

部门工资前三高的所有员工

Employee 表包含所有员工信息,每个员工有其对应的工号 Id,姓名 Name,工资 Salary 和部门编号 DepartmentId 。

https://leetcode-cn.com/problems/department-top-three-salaries/

题目太长不复制全部了,这题感觉要考虑的情况就多了,然而依然没有一个能有一个比较清晰的想法贯穿我的整个思维,讲得普通点,就是想不出来咯。。。先放在这里,晚上再想一下。

第二天:看了下官方题解,类比最高工资和分数排名,懂了思路:

SELECT
    d.Name AS 'Department', e1.Name AS 'Employee', e1.Salary
FROM
    Employee e1
        JOIN
    Department d ON e1.DepartmentId = d.Id
WHERE
    3 > (SELECT
            COUNT(DISTINCT e2.Salary)
        FROM
            Employee e2
        WHERE
            e2.Salary > e1.Salary
                AND e1.DepartmentId = e2.DepartmentId
        )
;

然后又挑了一个比较好理解的,在这里记录一下:

select dptm.Name as Department, emp1.Name as Employee, emp1.Salary
from Employee emp1
join Employee emp2 on emp1.DepartmentId = emp2.DepartmentId and emp1.Salary <= emp2.Salary
join Department dptm on emp1.DepartmentId = dptm.Id
group by emp1.Id
having count(distinct emp2.Salary) <= 3
order by dptm.Id, emp1.Salary desc, emp1.Id

2019/8/11:第二高的薪水和第N高的薪水

第二高的薪水

编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。

+----+--------+
| Id | Salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+

例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null。

+---------------------+
| SecondHighestSalary |
+---------------------+
| 200                 |
+---------------------+

链接:https://leetcode-cn.com/problems/second-highest-salary

这题看完题目就大概猜到用哪个函数,当前也不是没想过正向把这题解出来,正向的方法大概可以先找出第一个然后排除,再从排除里的找到最大的那个就是第二,但那样效率太低,不过如果不存在的话就不需要多加判断了。我还是先从limit函数走吧,因为很少用,正好这里复习一下:

分页的其他使用:offset
SQL查询语句中的 limit 与 offset 的区别:
limit y 分句表示: 读取 y 条数据
limit x, y 分句表示: 跳过 x 条数据,读取 y 条数据
limit y offset x 分句表示: 跳过 x 条数据,读取 y 条数据

然后可以写出sql:

select 
IFNULL((select distinct Salary from Employee order by Salary desc limit 1,1),null) 
as SecondHighestSalary
# 可以先写出一个简单版本,不包含ifnull的,这个我也是后来才看到如果是没有第二个则为null

SELECT MAX(Salary) AS SecondHighestSalary
FROM Employee
where salary < (
SELECT MAX(Salary)
FROM Employee
)
# 这种就是正向查询了,也就是先找第一个再找第二个,但如果是第三个就很难写了,所以推荐还是第一种写法

第N高的薪水

没有思路,看了下题解,原来是用函数:

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
DECLARE M INT;
SET M=N-1;
  RETURN (
      # Write your MySQL query statement below.
      SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT M, 1
  );
END

知道有这么个概念,但从来没用过,这里记录一下,以后回来复习。

2019/8/12:上升的温度和叶节点

上升的温度

给定一个 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 |
+----+

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rising-temperature
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这里看着是简单题,然而不太懂日期里面的相应函数,想到了是要日期相比,否则不可能给这个字段,但还是没有想到哪个函数,然后看了下题解,使用DATEDIFF:可以计算两个日期的时间差。

SELECT
    weather.id AS 'Id'
FROM
    weather
        JOIN
    weather w ON DATEDIFF(weather.date, w.date) = 1
        AND weather.Temperature > w.Temperature

树节点

对于 tree 表,id 是树节点的标识,p_id 是其父节点的 id。

+----+------+
| id | p_id |
+----+------+
| 1  | null |
| 2  | 1    |
| 3  | 1    |
| 4  | 2    |
| 5  | 2    |
+----+------+

每个节点都是以下三种类型中的一种:

Leaf: 如果节点是根节点。
Root: 如果节点是叶子节点。
Inner: 如果节点既不是根节点也不是叶子节点。
写一条查询语句打印节点id及对应的节点类型。按照节点id排序。上面例子的对应结果为:

+----+------+
| id | Type |
+----+------+
| 1  | Root |
| 2  | Inner|
| 3  | Leaf |
| 4  | Leaf |
| 5  | Leaf |
+----+------+

说明:
节点’1’是根节点,因为它的父节点为NULL,有’2’和’3’两个子节点。
节点’2’是内部节点,因为它的父节点是’1’,有子节点’4’和’5’。
节点’3’,‘4’,'5’是叶子节点,因为它们有父节点但没有子节点。
下面是树的图形:


        1
      /   \
    2       3
  /   \
4       5

注意:

如果一个树只有一个节点,只需要输出根节点属性。


这题可以看成是二叉树的数据结构在sql中的应用,题目意思是需要我们针对二叉树的结构来定义他们相应节点的名词,然后我们就可以用case when来分别对上述的三种情况标号:

select t1.id, 
case 
    when t1.p_id is Null then 'Root' 
    when (select count(*) from tree t2 where t1.id = t2.p_id) = 0
    then 'Leaf'
    when (select count(*) from tree t3 where t1.id = t3.p_id) > 0
    then 'Inner' 
end as Type
from tree t1

2019/8/15:最后三题

查询回答率最高的问题

求出survey_log表中回答率最高的问题,表格的字段有:uid, action, question_id, answer_id, q_num, timestamp。
uid是用户id;action的值为:“show”, “answer”, “skip”;当action是"answer"时,answer_id不为空,相反,当action是"show"和"skip"时为空(null);q_num是问题的数字序号。
写一条sql语句找出回答率最高的问题。

https://leetcode-cn.com/problems/get-highest-answer-rate-question/

这题的比率一般都是可以直接相除,所以sql为:

select question_id as survey_log
from(
select (sum(case when `action` like 'answer' then 1 else 0 end) / sum(case when `action` like 'show' then 1 else 0 end)) as rate,question_id
from survey_log
group by question_id
order by rate desc
limit 1) x

平面上最近距离

point_2d 表包含一个平面内一些点(超过两个)的坐标值(x,y)。

写一条查询语句求出这些点中的最短距离并保留2位小数。

链接:https://leetcode-cn.com/problems/shortest-distance-in-a-plane/

这个根据定义就可以直接写出了,运用欧氏距离,首先确立两表联查,然后再通过公式找到最小值,那么可以写出sql为:

select round(sqrt(min(power((p1.x-p2.x),2)+power((p1.y-p2.y),2))),2) as shortest
from point_2d p1,point_2d p2
where p1.x<>p2.x  or p1.y<>p2.y

最后需要注意的是两表联查后选中的数不能相同,因为相同则是0,那么就没有意义。

行程与用户

Trips 表中存所有出租车的行程信息。每段行程有唯一键 Id,Client_Id 和 Driver_Id 是 Users 表中 Users_Id 的外键。Status 是枚举类型,枚举成员为 (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’)。

+----+-----------+-----------+---------+--------------------+----------+
| Id | Client_Id | Driver_Id | City_Id |        Status      |Request_at|
+----+-----------+-----------+---------+--------------------+----------+
| 1  |     1     |    10     |    1    |     completed      |2013-10-01|
| 2  |     2     |    11     |    1    | cancelled_by_driver|2013-10-01|
| 3  |     3     |    12     |    6    |     completed      |2013-10-01|
| 4  |     4     |    13     |    6    | cancelled_by_client|2013-10-01|
| 5  |     1     |    10     |    1    |     completed      |2013-10-02|
| 6  |     2     |    11     |    6    |     completed      |2013-10-02|
| 7  |     3     |    12     |    6    |     completed      |2013-10-02|
| 8  |     2     |    12     |    12   |     completed      |2013-10-03|
| 9  |     3     |    10     |    12   |     completed      |2013-10-03| 
| 10 |     4     |    13     |    12   | cancelled_by_driver|2013-10-03|
+----+-----------+-----------+---------+--------------------+----------+

Users 表存所有用户。每个用户有唯一键 Users_Id。Banned 表示这个用户是否被禁止,Role 则是一个表示(‘client’, ‘driver’, ‘partner’)的枚举类型。

+----------+--------+--------+
| Users_Id | Banned |  Role  |
+----------+--------+--------+
|    1     |   No   | client |
|    2     |   Yes  | client |
|    3     |   No   | client |
|    4     |   No   | client |
|    10    |   No   | driver |
|    11    |   No   | driver |
|    12    |   No   | driver |
|    13    |   No   | driver |
+----------+--------+--------+

写一段 SQL 语句查出 2013年10月1日 至 2013年10月3日 期间非禁止用户的取消率。基于上表,你的 SQL 语句应返回如下结果,取消率(Cancellation Rate)保留两位小数。

+------------+-------------------+
|     Day    | Cancellation Rate |
+------------+-------------------+
| 2013-10-01 |       0.33        |
| 2013-10-02 |       0.00        |
| 2013-10-03 |       0.50        |
+------------+-------------------+

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trips-and-users
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

有些没懂意思,然后看一个题解看懂了:

select distinct b.Request_at as Day,Round(1-(select count(*)
from Trips a
where a.Client_Id not in(select Users_id from Users where Banned='Yes') and a.Driver_Id not in(select Users_id from Users where Banned='Yes') and a.Request_at=b.Request_at  and a.Status='completed')/(select count(*)
from Trips a
where a.Client_Id not in(select Users_id from Users where Banned='Yes') and a.Driver_Id not in(select Users_id from Users where Banned='Yes') and a.Request_at=b.Request_at),2) as 'Cancellation Rate'
from Trips b
where b.Request_at>= '2013-10-01' and  b.Request_at<='2013-10-03'

#1、内层计算每个日期No的总人数
#2、内层计算1中对应的complete人数
#3、内层1/2计算未取消的分数值,然后1-这个分数值,得到取消率
#4、由于内层日期不能人为指定,需要外层传入日期值
#5、在外层指定日期区间,因为内层指定了也没用(因为1-这个操作会导致日期区间失效)

猜你喜欢

转载自blog.csdn.net/submarineas/article/details/98487338
今日推荐