CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT BEGIN RETURN ( # Write your MySQL query statement below. select ( select distinct salary from ( select salary, dense_rank() over (order by salary desc) rnk from employee )t where rnk=N )getNthHighestSalary ); END
1 2 3 4 5 6 7
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT BEGIN SET N=N-1; RETURN ( SELECT distinct salary FROM Employee ORDER BY salary DESC LIMIT N, 1 ); END
1 2 3 4 5 6 7 8 9 10 11 12 13
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT BEGIN RETURN ( # Write your MySQL query statement below. with t1 as ( select * ,dense_rank() over (order by Salary desc) as rk from Employee ) select distinct ifnull(Salary ,null) from t1 where rk = N ); END
1 2 3 4 5 6 7 8 9 10 11
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT BEGIN DECLARE M INT; SET M = N-1; RETURN ( SELECT DISTINCT salary FROM Employee ORDER BY salary DESC LIMIT M, 1 ); END
178.分数排名 dense_rank b.score >= a.score
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
表: Scores
+-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | score | decimal | +-------------+---------+ id 是该表的主键(有不同值的列)。 该表的每一行都包含了一场比赛的分数。Score 是一个有两位小数点的浮点值。
select a.score as Score, count(DISTINCT b.score) AS Rank # 统计b表符合条件的不重复的分数的数量作为排名 FROM scores a join scores b where b.score >= a.score # 条件是这个分数不小于我,因为a、b表数据相同,所以排名值最小是1 group by a.id # a表中每个数据都进行排名 order by a.score DESC # 最后按分数(跟排名一样)降序排列
表:Logs +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | num | varchar | +-------------+---------+ 在 SQL 中,id 是该表的主键。 id 是一个自增列。
select distinct p.num as ConsecutiveNums from( select id, num, lag(num,1)over(order by id) num1, lag(num,2)over(order by id) num2 from Logs ) p where p.num = p.num1 and p.num1 = p.num2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# Write your MySQL query statement below with p as( ( select id, num, lag(num,1)over(order by id) num1, lag(num,2)over(order by id) num2, lead(num,1)over(order by id) num3, lead(num,2)over(order by id) num4 from Logs )
) select distinct p.num as ConsecutiveNums from p where p.num = p.num1 and p.num1 = p.num2 || p.num1 = p.num = p.num3 || p.num = p.num3 = p.num4
1 2 3 4 5 6 7 8 9 10
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
1 2 3
select distinct a.Num as ConsecutiveNums from Logs as a,Logs as b,Logs as c where a.Num=b.Num and b.Num=c.Num and a.id=b.id-1 and b.id=c.id-1;
184.部门工资最高的员工
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
SELECT d.name AS Department, e.name AS Employee, e.salary AS Salary FROM ( SELECT name, salary, departmentId, RANK() OVER(PARTITION BY departmentId ORDER BY salary DESC) AS `rank` FROM Employee ) e LEFT JOIN Department d ON e.departmentId = d.id WHERE e.`rank` = 1
1 2 3 4 5 6 7 8 9 10 11
# Write your MySQL query statement below select d.Name as Department, e.Name as Employee, e.Salary from Employee e,Department d where e.DepartmentId=d.id and (e.Salary,e.DepartmentId) in (select max(Salary),DepartmentId from Employee group by DepartmentId);
+--------------+---------+ | Column Name | Type | +--------------+---------+ | id | int | | name | varchar | | salary | int | | departmentId | int | +--------------+---------+ id 是该表的主键列(具有唯一值的列)。 departmentId 是 Department 表中 ID 的外键(reference 列)。 该表的每一行都表示员工的ID、姓名和工资。它还包含了他们部门的ID。
表: Department
+-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | name | varchar | +-------------+---------+ id 是该表的主键列(具有唯一值的列)。 该表的每一行表示部门ID和部门名。
# Write your MySQL query statement below with t as( select e1.departmentId,count(distinct e2.Salary) as r,e1.id from Employee e1 join Employee e2 on e1.departmentId = e2.departmentId and e1.salary <= e2.salary group by e1.id having r<3 )
select d.name as Department,e.name as Employee,e.salary as Salary from Department as d,t,Employee as e where t.departmentId = d.id and t.id = e.id
1
dense_rank()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
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 ) ;
196.删除重复的电子邮箱 连表delete
1 2 3 4 5 6 7 8 9 10 11 12 13
表: Person
+-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | email | varchar | +-------------+---------+ id 是该表的主键列(具有唯一值的列)。 该表的每一行包含一封电子邮件。电子邮件将不包含大写字母。
编写解决方案 删除 所有重复的电子邮件,只保留一个具有最小 id 的唯一电子邮件。
1 2
delete b from person a join person b on a.email = b.email and b.id > a.id
1 2 3 4 5 6 7 8 9
with t as (select min(id) id,email from Person group by email having count(*) > 1)
delete Person from Person,t where Person.id !=t.id and Person.email = t.email
197.上升的温度 datediff lag date_add
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
表: Weather
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | recordDate | date | | temperature | int | +---------------+---------+ id 是该表具有唯一值的列。 没有具有相同 recordDate 的不同行。 该表包含特定日期的温度信息
编写解决方案,找出与之前(昨天的)日期相比温度更高的所有日期的 id 。
1 2 3 4
select a.id from weather a, weather b where a.temperature > b.temperature and datediff(a.recordDate, b.recordDate) = 1;
SELECT T.request_at AS `Day`, ROUND( SUM( IF(T.STATUS = 'completed',0,1) ) / COUNT(T.STATUS), 2 ) AS `Cancellation Rate` FROM Trips AS T JOIN Users AS U1 ON (T.client_id = U1.users_id AND U1.banned ='No') JOIN Users AS U2 ON (T.driver_id = U2.users_id AND U2.banned ='No') WHERE T.request_at BETWEEN '2013-10-01' AND '2013-10-03' GROUP BY T.request_at
1
case when
avg精彩用法
1 2 3 4 5 6 7 8 9 10 11
# 精彩 # Write your MySQL query statement below SELECT request_at as 'Day', round(avg(Status!='completed'), 2) as 'Cancellation Rate' FROM trips t JOIN users u1 ON (t.client_id = u1.users_id AND u1.banned = 'No') JOIN users u2 ON (t.driver_id = u2.users_id AND u2.banned = 'No') WHERE request_at BETWEEN '2013-10-01' AND '2013-10-03' GROUP BY request_at
534.游戏玩法分析 III sum() over(partition by
1 2 3 4 5 6 7 8 9 10 11 12 13
表:Activity
+--------------+---------+ | Column Name | Type | +--------------+---------+ | player_id | int | | device_id | int | | event_date | date | | games_played | int | +--------------+---------+ (player_id,event_date)是此表的主键(具有唯一值的列)。 这张表显示了某些游戏的玩家的活动情况。 每一行是一个玩家的记录,他在某一天使用某个设备注销之前登录并玩了很多游戏(可能是 0 )。
-- 方案一: select a1.player_id, a1.event_date, sum(a2.games_played) as games_played_so_far from Activity a1 join Activity a2 on a1.player_id=a2.player_id and a1.event_date>=a2.event_date -- 关联当前时间之前的数据 group by a1.player_id,a1.event_date; -- 方案二: select player_id, event_date, sum(games_played) over(partition by player_id order by event_date) games_played_so_far from Activity;
难 569.游戏玩法分析 IV partition by 中位数
1 2 3 4 5 6 7 8 9 10 11 12 13
SELECT Id, Company, salary FROM Employee WHERE Id in (SELECT E1.Id FROM Employee AS E1 JOIN Employee AS E2 ON E1.company = E2.Company GROUP BY E1.Id HAVING SUM(IF(E1.Salary >=E2.Salary,1,0))>= COUNT(*)/ 2 AND SUM(IF(E1.Salary<=E2.salary,1,0))>= COUNT(*)/ 2) GROUP BY Company,Salary ORDER BY Company
1 2 3 4 5 6 7 8 9 10
--方法一: --注意事项:排序时用row_number,会有排名相同的情况 --中位数的逻辑了解:不论个数是奇数偶数,中位数在总数除以2和总数除以2加1之间 select id ,company,salary from ( select * ,row_number() over(partition by company order by salary) as rnk ,count(*) over(partition by company ) as cnt from Employee) a where rnk BETWEEN cnt*1.0/2 AND cnt*1.0/2 + 1
SELECT * FROM ( SELECT N1.NUMBER, SUM(IF(N2.frequency IS NULL,0,N2.frequency)) AS `beg` FROM numbers AS N1 LEFT JOIN numbers AS N2 ON (N1.NUMBER > N2.NUMBER) GROUP BY N1.number ORDER BY N1.NUMBER ) AS A JOIN ( SELECT N1.NUMBER, SUM(IF(N2.frequency IS NULL,0,N2.frequency)) AS `end` FROM numbers AS N1 LEFT JOIN numbers AS N2 ON (N1.NUMBER >= N2.NUMBER) GROUP BY N1.number ORDER BY N1.number ) AS B ON (A.NUMBER = B.NUMBER) JOIN ( SELECT FLOOR((SUM(N.frequency)-1)/2) AS `beg`, if(SUM(N.frequency)%2=1,0,1) AS `cnt` FROM numbers AS N ) AS C ON ( ( (C.beg <= A.beg AND A.beg < (C.beg +C.cnt+1)) OR (C.beg < B.END AND B.END <= (C.beg +C.cnt+1)) ) OR ( (A.beg <= C.beg AND C.beg < B.end) OR (A.beg < (C.beg+C.cnt+1) AND (C.beg+C.cnt+1) <= B.END) ) )
select question_id from ( select question_id, sum(if(action='answer',1,0)) as ans_num, sum(if(action='show',1,0)) as cout_num from survey_log group by question_id ) as temp order by ans_num / cout_num desc limit 1;
SELECT temp.Id, temp.Month, sum( temp.Salary ) over ( PARTITION BY temp.Id ORDER BY temp.Month ) AS salary FROM ( SELECT Id, Month, Salary, DENSE_RANK() over ( PARTITION BY Id ORDER BY Month DESC ) AS rnk FROM employee_579 ) AS temp WHERE temp.rnk > 1 ORDER BY temp.Id, temp.Month DESC;
1 2 3 4 5 6 7 8 9 10 11
with tmp as( select *, rank() over(partition by id order by month desc) as rn from Employee ) select id,month, sum(salary) over(partition by id order by month range between 2 preceding and current row) as salary from tmp where rn != 1 order by id ,month desc;
1 2 3 4 5 6 7 8
SELECT t.id, t.`month`, t.salary FROM ( SELECT id, `month`, SUM(salary) over(PARTITION BY id ORDER BY `month` ROWS 2 PRECEDING) salary, -- 累加的总薪水 rank() over(PARTITION BY id ORDER BY `month` DESC) ranks -- 排名好去掉最近一个月 FROM employee ) t WHERE t.ranks > 1
# Write your MySQL query statement below SELECT dept_name, COUNT(student_id) AS student_number FROM Department LEFT JOIN Student USING (dept_id) GROUP BY dept_id ORDER BY 2 DESC, 1;
select round(sum(tiv_2016),2) tiv_2016 from (select e1.pid pid,e1.tiv_2016 from Insurance e1,Insurance e2 where e1.tiv_2015=e2.tiv_2015 and e1.pid != e2.pid group by e1.pid having count(*)>0 ) t1 where pid not in (select e1.pid from Insurance e1,Insurance e2 where e1.lat =e2.lat and e1.lon =e2.lon and e1.pid != e2.pid)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
SELECT ROUND(SUM(tiv_2016), 2) AS tiv_2016 FROM Insurance WHERE tiv_2015 IN ( SELECT tiv_2015 FROM Insurance GROUP BY tiv_2015 HAVING COUNT(*) > 1 ) AND (lat, lon) NOT IN ( SELECT lat, lon FROM Insurance GROUP BY lat, lon HAVING COUNT(*) > 1 )
+----------------+---------+ | Column Name | Type | +----------------+---------+ | sender_id | int | | send_to_id | int | | request_date | date | +----------------+---------+ 该表可能包含重复项(换句话说,在SQL中,该表没有主键)。 该表包含发送请求的用户的 ID ,接受请求的用户的 ID 以及请求的日期。
表:RequestAccepted
+----------------+---------+ | Column Name | Type | +----------------+---------+ | requester_id | int | | accepter_id | int | | accept_date | date | +----------------+---------+ 该表可能包含重复项(换句话说,在SQL中,该表没有主键)。 该表包含发送请求的用户的 ID ,接受请求的用户的 ID 以及请求通过的日期。
# Write your MySQL query statement below SELECT ROUND( IFNULL( ( SELECT COUNT(DISTINCT requester_id, accepter_id) FROM RequestAccepted ) / (SELECT COUNT(DISTINCT sender_id, send_to_id) FROM FriendRequest), 0 ), 2 ) AS accept_rate;
601.体育馆的人流量 lag() lead() leaset()
1 2 3 4 5 6 7 8 9 10 11 12 13 14
with people as ( select id, visit_date, people, Lag(people,2) over(order by id) as pprvPeople, Lag(people,1) over(order by id) as prvPeople, Lead(people,1) over(order by id) as nextPeople, Lead(people,2) over(order by id) as nnextPeople from stadium ) select id, visit_date, people from people where (people >= 100 and prvPeople>=100 and pprvPeople>=100) || (people >= 100 and nextPeople>=100 and nnextPeople>=100) || (people >= 100 and nextPeople>=100 and prvPeople>=100)
1 2 3 4 5 6 7 8 9 10 11
select distinct s1.* from stadium s1, stadium s2, stadium s3 where s1.people >= 100 and s2.people>= 100 and s3.people >= 100 and ( (s1.id - s2.id = 1 and s2.id - s3.id =1) or (s2.id - s1.id = 1 and s1.id - s3.id =1) or (s3.id - s2.id = 1 and s2.id - s1.id = 1) ) order by s1.id;
1 2 3 4 5 6 7 8 9 10 11
select id, visit_date, people from (select id, visit_date, people, lag(people, 1, 0) over(order by id) as previous1_num, lag(people, 2, 0) over(order by id) as previous2_num, lead(people, 1, 0) over(order by id) as next1_num, lead(people, 2, 0) over(order by id) as next2_num from Stadium) a where least(a.people, a.previous1_num, a.previous2_num)>=100 or least(a.people, a.next1_num, a.next2_num)>=100 or least(a.people, a.next1_num, a.previous1_num)>=100
602 case when
1 2 3 4 5 6 7 8 9 10 11
select case when requester_id is not null then requester_id else accepter_id end as id, if(c1 is null,0,c1)+if(c2 is null,0,c2) as num from (select requester_id,count(*) c1 from RequestAccepted group by requester_id) t1 left join (select accepter_id,count(*) c2 from RequestAccepted group by accepter_id) t2 on t1.requester_id=t2.accepter_id order by num desc limit 1
603.连续空余座位 lag lead ROWS BETWEEN AND
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
表: Cinema
+-------------+------+ | Column Name | Type | +-------------+------+ | seat_id | int | | free | bool | +-------------+------+ Seat_id 是该表的自动递增主键列。 在 PostgreSQL 中,free 存储为整数。请使用 ::boolean 将其转换为布尔格式。 该表的每一行表示第 i 个座位是否空闲。1 表示空闲,0 表示被占用。
查找电影院所有连续可用的座位。
返回按 seat_id 升序排序 的结果表。
测试用例的生成使得两个以上的座位连续可用。
1 2 3 4 5 6 7 8 9 10 11 12
# Write your MySQL query statement below WITH T AS ( SELECT seat_id, (free + (LAG(free) OVER (ORDER BY seat_id))) AS a, (free + (LEAD(free) OVER (ORDER BY seat_id))) AS b FROM Cinema ) SELECT seat_id FROM T WHERE a = 2 OR b = 2;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# Write your MySQL query statement below WITH T AS ( SELECT *, SUM(free = 1) OVER ( ORDER BY seat_id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) AS cnt FROM Cinema ) SELECT seat_id FROM T WHERE free = 1 AND cnt > 1 ORDER BY 1;
608 union
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# Write your MySQL query statement below select id,'Root' as type from Tree where p_id is null union select id,'Inner' as type from Tree where p_id is not null and id not in( select t2.id from Tree t1 right join Tree t2 on t1.p_id=t2.id where t1.id is null and t2.id is not null and t2.p_id is not null) union select t2.id, 'Leaf' as type from Tree t1 right join Tree t2 on t1.p_id=t2.id where t1.id is null and t2.id is not null and t2.p_id is not null
610.判断三角形
1 2 3 4 5 6 7 8 9 10 11 12 13 14
表: Triangle
+-------------+------+ | Column Name | Type | +-------------+------+ | x | int | | y | int | | z | int | +-------------+------+ 在 SQL 中,(x, y, z)是该表的主键列。 该表的每一行包含三个线段的长度。
对每三个线段报告它们是否可以形成一个三角形。
1 2 3 4
# Write your MySQL query statement below
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
表: Seat +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | student | varchar | +-------------+---------+ id 是该表的主键(唯一值)列。 该表的每一行都表示学生的姓名和 ID。 ID 序列始终从 1 开始并连续增加。
编写解决方案来交换每两个连续的学生的座位号。如果学生的数量是奇数,则最后一个学生的id不交换。 按 id 升序 返回结果表。 查询结果格式如下所示。
select if(id=count(*)+1,id-1,id) id,student from (select id-1 id,student from student where id%2=0) union (select id+1 id,student from student where id%2=1) u order by id
627.变更性别 update replace
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Salary 表:
+-------------+----------+ | Column Name | Type | +-------------+----------+ | id | int | | name | varchar | | sex | ENUM | | salary | int | +-------------+----------+ id 是这个表的主键(具有唯一值的列)。 sex 这一列的值是 ENUM 类型,只能从 ('m', 'f') 中取。 本表包含公司雇员的信息。
# 1. update salary set sex = ( case sex when 'm' then 'f' else 'm' end );
# 2. update salary set sex = if(sex='m','f','m');
# 3. update salary set sex = char(ascii('m') + ascii('f') - ascii(sex));
1 2 3 4
update Salary set sex = replace("mf", sex, "");
相当于把"mf"中与sex相同的换为空字符串,也就是删除了,剩下的是对立的性别
1070.产品销售分析 川
1 2 3 4 5 6
select product_id,year as first_year,quantity,price from( select product_id,year,quantity,price,ROW_NUMBER() over(partition by product_id order by year) as r from Sales ) t where t.r=1
# Write your MySQL query statement below SELECT buyer_id FROM Sales JOIN Product USING (product_id) GROUP BY 1 HAVING SUM(product_name = 'S8') > 0 AND SUM(product_name = 'iPhone') = 0;
+--------------+---------+ | Column Name | Type | +--------------+---------+ | player_id | int | | device_id | int | | event_date | date | | games_played | int | +--------------+---------+ (player_id,event_date)是此表的主键(具有唯一值的列的组合) 这张表显示了某些游戏的玩家的活动情况 每一行表示一个玩家的记录,在某一天使用某个设备注销之前,登录并玩了很多游戏(可能是 0)
玩家的 安装日期 定义为该玩家的第一个登录日。
我们将日期 x 的 第一天留存率 定义为:假定安装日期为 X 的玩家的数量为 N ,其中在 X 之后的一天重新登录的玩家数量为 M,M/N 就是第一天留存率,四舍五入到小数点后两位。
编写解决方案,报告所有安装日期、当天安装游戏的玩家数量和玩家的 第一天留存率。
以 任意顺序 返回结果表。
1 2 3 4 5 6 7 8 9 10 11
with t as( select player_id,min(event_date) from Activity group by player_id )
select t.event_date install_dt,count(*) installs,count(a.player_id)/ count(*) Day1_retention from t left join Activity a on t.player_id = a.player_id and DATEDIFF(t.event_date,a.event_date)=1 group by t.event_date
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# Write your MySQL query statement below WITH T AS ( SELECT player_id, event_date, MIN(event_date) OVER (PARTITION BY player_id) AS install_dt FROM Activity ) SELECT install_dt, COUNT(DISTINCT player_id) AS installs, ROUND( SUM(DATEDIFF(event_date, install_dt) = 1) / COUNT(DISTINCT player_id), 2 ) AS day1_retention FROM T GROUP BY 2;
# Write your MySQL query statement below SELECT book_id, name FROM Books LEFT JOIN Orders USING (book_id) WHERE available_from < '2019-05-23' GROUP BY 1 HAVING SUM(IF(dispatch_date >= '2018-06-23', quantity, 0)) < 10;
1107.每日新用户统计 MIN() OVER (PARTITION BY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Traffic 表:
+---------------+---------+ | Column Name | Type | +---------------+---------+ | user_id | int | | activity | enum | | activity_date | date | +---------------+---------+ 该表可能有重复的行。 activity 列是 ENUM 类型,可能取 ('login', 'logout', 'jobs', 'groups', 'homepage') 几个值之一。
with t as( select user_id,min(activity_date) time from Traffic where DATEDIFF('2019-06-30', activity_date) <= 90 and activity='login' group by user_id )
select time login_date,count(*) user_count from t group by time
1 2 3 4 5 6 7 8 9 10 11 12 13
# Write your MySQL query statement below WITH T AS ( SELECT user_id, MIN(activity_date) OVER (PARTITION BY user_id) AS login_date FROM Traffic WHERE activity = 'login' ) SELECT login_date, COUNT(DISTINCT user_id) AS user_count FROM T WHERE DATEDIFF('2019-06-30', login_date) <= 90 GROUP BY 2;
select spend_date,platform, sum(amount) as total_amount, count(user_id) total_users from (select spend_date, user_id, (case count(distinct platform) when 1 then platform when 2 then 'both' end ) as platform, sum(amount) as amount from Spending group by spend_date, user_id ) as temp2 group by spend_date, platform
# Write your MySQL query statement below WITH P AS ( SELECT DISTINCT spend_date, 'desktop' AS platform FROM Spending UNION SELECT DISTINCT spend_date, 'mobile' FROM Spending UNION SELECT DISTINCT spend_date, 'both' FROM Spending ), T AS ( SELECT user_id, spend_date, SUM(amount) AS amount, IF(COUNT(platform) = 1, platform, 'both') AS platform FROM Spending GROUP BY 1, 2 ) SELECT p.*, IFNULL(SUM(amount), 0) AS total_amount, COUNT(t.user_id) AS total_users FROM P AS p LEFT JOIN T AS t USING (spend_date, platform) GROUP BY 1, 2;
# Write your MySQL query statement below SELECT u.user_id AS seller_id, CASE WHEN u.favorite_brand = i.item_brand THEN 'yes' ELSE 'no' END AS 2nd_item_fav_brand FROM users AS u LEFT JOIN ( SELECT order_date, item_id, seller_id, RANK() OVER ( PARTITION BY seller_id ORDER BY order_date ) AS rk FROM orders ) AS o ON u.user_id = o.seller_id AND o.rk = 2 LEFT JOIN items AS i ON o.item_id = i.item_id;
1174.即时食物配送Ⅱ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
配送表: Delivery
+-----------------------------+---------+ | Column Name | Type | +-----------------------------+---------+ | delivery_id | int | | customer_id | int | | order_date | date | | customer_pref_delivery_date | date | +-----------------------------+---------+ delivery_id 是该表中具有唯一值的列。 该表保存着顾客的食物配送信息,顾客在某个日期下了订单,并指定了一个期望的配送日期(和下单日期相同或者在那之后)。
如果顾客期望的配送日期和下单日期相同,则该订单称为 「即时订单」,否则称为「计划订单」。
「首次订单」是顾客最早创建的订单。我们保证一个顾客只会有一个「首次订单」。
编写解决方案以获取即时订单在所有用户的首次订单中的比例。保留两位小数。
1 2 3 4 5 6 7 8 9 10
with t as (select customer_id,min(order_date) from Delivery group by customer_id )
select round(count(d.customer_id)/count(t.customer_id)*100,2) from t left join Delivery d on t.customer_id = d.customer_id and t.order_date = d.order_date and d.order_date = d.customer_pref_delivery_date
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
WITH FirstOrders AS ( SELECT customer_id, order_date, customer_pref_delivery_date, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) AS rn FROM Delivery ) SELECT ROUND( SUM(CASE WHEN order_date = customer_pref_delivery_date THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2 ) AS immediate_percentage FROM FirstOrders WHERE rn = 1; -- 只考虑首次订单
1 2 3 4 5
select round(sum(order_date = customer_pref_delivery_date)/count(*)*100,2) immediate_percentage from Delivery where (customer_id,order_date) in (select customer_id,min(order_date) from Delivery group by customer_id)
SELECT id, SUM(IF(month = 'Jan', revenue, NULL)) AS Jan_Revenue, SUM(IF(month = 'Feb', revenue, NULL)) AS Feb_Revenue, SUM(IF(month = 'Mar', revenue, NULL)) AS Mar_Revenue, SUM(IF(month = 'Apr', revenue, NULL)) AS Apr_Revenue, SUM(IF(month = 'May', revenue, NULL)) AS May_Revenue, SUM(IF(month = 'Jun', revenue, NULL)) AS Jun_Revenue, SUM(IF(month = 'Jul', revenue, NULL)) AS Jul_Revenue, SUM(IF(month = 'Aug', revenue, NULL)) AS Aug_Revenue, SUM(IF(month = 'Sep', revenue, NULL)) AS Sep_Revenue, SUM(IF(month = 'Oct', revenue, NULL)) AS Oct_Revenue, SUM(IF(month = 'Nov', revenue, NULL)) AS Nov_Revenue, SUM(IF(month = 'Dec', revenue, NULL)) AS Dec_Revenue FROM Department GROUP BY id
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
select id ,sum(case when month = 'Jan' then revenue else null end) Jan_Revenue ,sum(case when month = 'Feb' then revenue else null end) Feb_Revenue ,sum(case when month = 'Mar' then revenue else null end) Mar_Revenue ,sum(case when month = 'Apr' then revenue else null end) Apr_Revenue ,sum(case when month = 'May' then revenue else null end) May_Revenue ,sum(case when month = 'Jun' then revenue else null end) Jun_Revenue ,sum(case when month = 'Jul' then revenue else null end) Jul_Revenue ,sum(case when month = 'Aug' then revenue else null end) Aug_Revenue ,sum(case when month = 'Sep' then revenue else null end) Sep_Revenue ,sum(case when month = 'Oct' then revenue else null end) Oct_Revenue ,sum(case when month = 'Nov' then revenue else null end) Nov_Revenue ,sum(case when month = 'Dec' then revenue else null end) Dec_Revenue from Department group by 1
1193.每月交易| date_format(),left(),sub_string()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
表:Transactions
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | country | varchar | | state | enum | | amount | int | | trans_date | date | +---------------+---------+ id 是这个表的主键。 该表包含有关传入事务的信息。 state 列类型为 ["approved", "declined"] 之一。
编写一个 sql 查询来查找每个月和每个国家/地区的事务数及其总金额、已批准的事务数及其总金额。
以 任意顺序 返回结果表。
1 2 3 4 5 6 7 8 9 10
# Write your MySQL query statement below select date_format(trans_date,'%Y-%m') as month, country, count(*) as trans_count, sum(if(state='approved',1,0)) as approved_count, sum(amount) as trans_total_amount, sum(if(state='approved',amount,0)) as approved_total_amount from Transactions group by month,country
1 2 3 4 5 6 7
select left(T.trans_date,7) month, t.country,count(t.state) trans_count , sum(if(t.state='approved',1,0)) approved_count, sum(t.amount) trans_total_amount , sum(if(t.state='approved',t.amount,0)) approved_total_amount from Transactions T group by left(T.trans_date,7),t.country;
with t as( select player,sum(score)scoreall from (select first_player player,first_score score from Matches union all select second_player player,second_score score from Matches) a group by player )
with s as( select group_id,max(scoreall) maxscore from t,Players where t.player = Players.player_id group by group_id )
select s.group_id,min(player_id ) player_id from s, (select group_id,t.player player,scoreall from t,Players where t.player = Players.player_id) r where s.group_id = r.group.id and s.maxscore = r.scoreall group by s.group_id
# Write your MySQL query statement below WITH s AS ( SELECT first_player AS player_id, first_score AS score, group_id FROM Matches AS m JOIN Players AS p ON m.first_player = p.player_id UNION ALL SELECT second_player AS player_id, second_score AS score, group_id FROM Matches AS m JOIN Players AS p ON m.second_player = p.player_id ), t AS ( SELECT group_id, player_id, SUM(score) AS scores FROM s GROUP BY player_id ), p AS ( SELECT group_id, player_id, RANK() OVER ( PARTITION BY group_id ORDER BY scores DESC, player_id ) AS rk FROM t ) SELECT group_id, player_id FROM p WHERE rk = 1;
1204.最后一个能进入巴士的人
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
表: Queue +-------------+---------+ | Column Name | Type | +-------------+---------+ | person_id | int | | person_name | varchar | | weight | int | | turn | int | +-------------+---------+ person_id 是这个表具有唯一值的列。 该表展示了所有候车乘客的信息。 表中 person_id 和 turn 列将包含从 1 到 n 的所有数字,其中 n 是表中的行数。 turn 决定了候车乘客上巴士的顺序,其中 turn=1 表示第一个上巴士,turn=n 表示最后一个上巴士。 weight 表示候车乘客的体重,以千克为单位。
# Write your MySQL query statement below WITH T AS ( SELECT person_name, SUM(weight) OVER (ORDER BY turn) AS s FROM Queue ) SELECT person_name FROM T WHERE s <= 1000 ORDER BY s DESC LIMIT 1;
1 2 3 4 5 6 7 8 9 10
# Write your MySQL query statement below SELECT a.person_name FROM Queue AS a, Queue AS b WHERE a.turn >= b.turn GROUP BY a.person_id HAVING SUM(b.weight) <= 1000 ORDER BY a.turn DESC LIMIT 1;
Transactions 记录表 +----------------+---------+ | Column Name | Type | +----------------+---------+ | id | int | | country | varchar | | state | enum | | amount | int | | trans_date | date | +----------------+---------+ id 是这个表的主键。 该表包含有关传入事务的信息。 状态列是枚举类型,值为 [approved、declined] 其中之一的列。 Chargebacks 表
+----------------+---------+ | Column Name | Type | +----------------+---------+ | trans_id | int | | trans_date | date | +----------------+---------+ 退单包含有关放置在事务表中的某些事务的传入退单的基本信息。 trans_id 是 transactions 表的 id 列的外键(reference 列)。 每项退单都对应于之前进行的交易,即使未经批准。 编写一个解决方案,找出每个国家/地区的每月交易信息:已批准交易的数量及其总金额、退单的数量及其总金额。
select month, country, count(case when state = 'approved' and tag=0 then 1 else null end) as approved_count, sum(case when state = 'approved' and tag =0 then amount else 0 end)as approved_amount, count(case when tag =1 then 1 else null end)as chargeback_count, sum(case when tag =1 then amount else 0 end)as chargeback_amount from ( -- 每个月和每个国家/地区的已批准交易的数量 select id,country,state,amount,date_format(trans_date ,"%Y-%m")as month,0 as tag from Transactions where state = 'approved' union all -- 每个月和每个国家/地区的退单的数量 select id,country,state,amount,date_format(c.trans_date ,"%Y-%m")as month,1 as tag from Transactions as t inner join Chargebacks as c on t.id = c.trans_id )temp group by month,country
select trans_date, country, state, amount from Transactions where state = 'approved' union all select a.trans_date, b.country, 'declined' state, b.amount from Chargebacks a inner join Transactions b on a.trans_id = b.id ) select date_format(trans_date,'%Y-%m') month, country, count(case when state = 'approved' then 1 else null end) approved_count, sum(case when state = 'approved' then amount else 0 end) approved_amount, count(case when state = 'declined' then 1 else null end) chargeback_count, sum(case when state = 'declined' then amount else 0 end) chargeback_amount from tmp group by date_format(trans_date,'%Y-%m'),country;
# Write your MySQL query statement below WITH T AS ( SELECT * FROM Transactions UNION SELECT id, country, 'chargeback', amount, c.trans_date FROM Transactions AS t JOIN Chargebacks AS c ON t.id = c.trans_id ) SELECT DATE_FORMAT(trans_date, '%Y-%m') AS month, country, SUM(state = 'approved') AS approved_count, SUM(IF(state = 'approved', amount, 0)) AS approved_amount, SUM(state = 'chargeback') AS chargeback_count, SUM(IF(state = 'chargeback', amount, 0)) AS chargeback_amount FROM T GROUP BY 1, 2 HAVING approved_amount OR chargeback_amount;
with t as( select host_team,case when host_goals>guest_goals then 3 when host_goals=guest_goals then 1 when host_goals<guest_goals then 0 END host_team_score,guest_team,case when host_goals<guest_goals then 3 when host_goals=guest_goals then 1 when host_goals>guest_goals then 0 END guest_team_score from Matches )
select team_id,team_name,sum(num_points) num_points from (select host_team team_id,host_team_score num_points from t union all select guest_team team_id,guest_team_score num_points from t) ut,Teams where ut.team_id = Teams.team_id group by ut.team_id order by num_points DESC,team_id
select state as period_state, min(dt ) as start_date, max(dt) as end_date from ( select *,rank()over(partition by state order by dt ) as rk ,subdate(dt,rank()over(partition by state order by dt)) as dif from ( select 'succeeded' as 'state',success_date as 'dt' from Succeeded where success_date between '2019-01-01' and '2019-12-31' union select 'failed'as 'state',fail_date as 'dt' from Failed where fail_date between '2019-01-01' and '2019-12-31' )t1 )t2 group by state,dif order by dt
# Write your MySQL query statement below WITH T AS ( SELECT fail_date AS dt, 'failed' AS st FROM Failed WHERE YEAR(fail_date) = 2019 UNION ALL SELECT success_date AS dt, 'succeeded' AS st FROM Succeeded WHERE YEAR(success_date) = 2019 ) SELECT st AS period_state, MIN(dt) AS start_date, MAX(dt) AS end_date FROM ( SELECT *, SUBDATE( dt, RANK() OVER ( PARTITION BY st ORDER BY dt ) ) AS pt FROM T ) AS t GROUP BY 1, pt ORDER BY 2;
# Write your MySQL query statement below WITH T AS ( SELECT user1_id AS user_id FROM Friendship WHERE user2_id = 1 UNION SELECT user2_id AS user_id FROM Friendship WHERE user1_id = 1 ) SELECT DISTINCT page_id AS recommended_page FROM T JOIN Likes USING (user_id) WHERE page_id NOT IN (SELECT page_id FROM Likes WHERE user_id = 1);
1 2 3 4 5 6 7 8
with t as ( select case when user1_id=1 then user2_id case when user2_id=1 then user1_id end user_id from Friendship )
select page_id recommended_page from t,Likes where t.user_id = Likes.user_id and Likes.page_id not in (select page_id from Likes where user_id=1)
# Write your MySQL query statement below SELECT e1.employee_id FROM Employees AS e1 JOIN Employees AS e2 ON e1.manager_id = e2.employee_id JOIN Employees AS e3 ON e2.manager_id = e3.employee_id WHERE e1.employee_id != 1 AND e3.manager_id = 1;
1 2 3 4 5 6
with recursive temp as ( select e.employee_id from Employees e where e.employee_id!=1 and manager_id=1 union all select e.employee_id from Employees e join temp t on t.employee_id=e.manager_id ) select * from temp
with t as( select e.student_id student_id,student_name,subject_name,count(*) attended_exams from Examinations e,Students s where e.student_id = s.student_id group by e.student_id,subject_name )
with s as( select student_id,student_name,subject_name from Students,Subjects )
select s.student_id,s.student_name,s.subject_name,ifnull(attended_exams,0) attended_exams from s left join t on s.student_id = t.student_id and s.subject_name = t.subject_name order by student_id,subject_name
# Write your MySQL query statement below WITH T AS ( SELECT log_id, log_id - ROW_NUMBER() OVER (ORDER BY log_id) AS pid FROM Logs ) SELECT MIN(log_id) AS start_id, MAX(log_id) AS end_id FROM T GROUP BY pid;
select visited_on, amount, average_amount from (select row_number() over(order by visited_on) rn, visited_on, round(sum(amount) over (order by visited_on rows between 6 preceding and current row), 2) amount, round(avg(amount) over (order by visited_on rows between 6 preceding and current row)/7, 2) average_amount from (select visited_on, sum(amount) amount from Customer group by visited_on) temp) result where rn >= 7;
1 2 3 4 5 6 7 8 9 10 11
select visited_on, amount, average_amount from ( select distinct visited_on, # 因为窗口函数是按照日期计算的。所以相同日期的结果也是相同的,直接去重即可 sum(amount) over(order by visited_on range interval 6 day preceding) amount, # 按照日期排序,范围是当前日期和当前日期的前六天 round(sum(amount) over(order by visited_on range interval 6 day preceding)/7, 2) average_amount # 同理 from Customer) t where datediff(visited_on, (select min(visited_on) from Customer))>=6 #去除日期不足7日的结果 order by visited_on;
1
其实是先用窗口函数计算指定日期之内的销售总额,得到两个10号之前的总额,再去重,因为两个10号得到的金额是一样的。ROUND(SUM(amount) OVER (ORDER BY visited_on RANGE INTERVAL 6 DAY PRECEDING) / 7, 2) 计算这7天的消费平均值。这里的计算是针对每个日期的过去7天消费进行的,无论有多少顾客在这7天内消费,都将其总消费额平均。这里除以7就是因为窗口函数其实计算了八个顾客的总金额不能avg,只能除以七天
with t as( select l.user_id user_id,l.visit_date date,count(t.user_id) transactions_count from Visits l left join Transactions t on l.user_id = t.user_id and l.visit_date = t.transaction_date group by l.user_id,l.visit_date )
select transactions_count,count(distinct user_id) visits_count from t group by transactions_count
1369.获取最近第二次的活动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
表: UserActivity +---------------+---------+ | Column Name | Type | +---------------+---------+ | username | varchar | | activity | varchar | | startDate | Date | | endDate | Date | +---------------+---------+ 该表可能有重复的行 该表包含每个用户在一段时间内进行的活动的信息 名为 username 的用户在 startDate 到 endDate 日内有一次活动
SELECT username, activity, startdate, enddate FROM ( SELECT *, RANK() OVER ( PARTITION BY username ORDER BY startdate DESC ) AS rk, COUNT(username) OVER (PARTITION BY username) AS cnt FROM UserActivity ) AS a WHERE a.rk = 2 OR a.cnt = 1;
with s as( select product_id,product_name,Year(period_start) report_year,datediff(period_end,period_start)*average_daily_sales total_amount from Sales where Year(period_start)=Year(period_end) )
with t as( select product_id,product_name,period_start,case when Year(period_start)=2018 and Year(period_end)=2019 then Year(period_start)+'12-31' case when Year(period_start)=2019 and Year(period_end)=2020 then Year(period_start)+'12-31' m-year,period_end,average_daily_sales from Sales )
with d as( select product_id,product_name,period_start,'2018-12-31' m-year,365,'2020-1-1' mm-year,period_end,average_daily_sales from Sales where Year(period_start)=2018 and Year(period_end)=2020 )
select product_id,product_name,Year(period_start),datediff(m-year,period_start)*average_daily_sales total_amount from t union all select product_id,product_name,Year(period_end),datediff(period_end,date_add(m-year,interval 1 day)*average_daily_sales total_amount from t union all select * from s union all select product_id,product_name,Year(period_start),datediff(m-year,period_start)*average_daily_sales total_amount from d union all select product_id,product_name,2019,365*average_daily_sales total_amount from d union all select product_id,product_name,2020,datediff(period_end,mm-year)*average_daily_sales total_amount from d
with t as( select student_id from Exam a, (select exam_id,max(score) maxScore,min(score) minScore from Exam group by exam_id) s where a.exam_id = s.exam_id and (a.score = minScore OR a.score = maxScore) )
select student_id,student_name from Exam,Student where Exam.student_id = Student.student_id and Exam.student_id not in( select * from t ) order by student_id
# Write your MySQL query statement below WITH T AS ( SELECT student_id, RANK() OVER ( PARTITION BY exam_id ORDER BY score ) AS rk1, RANK() OVER ( PARTITION BY exam_id ORDER BY score DESC ) AS rk2 FROM Exam ) SELECT student_id, student_name FROM T JOIN Student USING (student_id) GROUP BY 1 HAVING SUM(rk1 = 1) = 0 AND SUM(rk2 = 1) = 0 ORDER BY 1;
1435.制作会话柱状图
1 2 3 4 5 6 7 8 9 10 11 12 13 14
表:Sessions +---------------------+---------+ | Column Name | Type | +---------------------+---------+ | session_id | int | | duration | int | +---------------------+---------+ session_id 是该表主键 duration 是用户访问应用的时间, 以秒为单位 你想知道用户在你的 app 上的访问时长情况。因此你决定统计访问时长区间分别为 "[0-5>","[5-10>","[10-15>" 和 "15 minutes or more" 的会话数量,并以此绘制柱状图。 写一个解决方案来报告 (bin, total) 。
返回结果 无顺序要求
1 2 3 4 5 6 7 8 9 10 11
select '[0-5>',sum(duration>=0 and duration<300) total from Sessions union all select '[5-10>',sum(duration>=300 and duration<600) total from Sessions union all select '[10-15>',sum(duration>=600 and duration<900) total from Sessions union all select '15 or more',sum(duration>=900) total from Sessions
表 Variables: +---------------+---------+ | Column Name | Type | +---------------+---------+ | name | varchar | | value | int | +---------------+---------+ 在 SQL 中,name 是该表主键. 该表包含了存储的变量及其对应的值. 表 Expressions: +---------------+---------+ | Column Name | Type | +---------------+---------+ | left_operand | varchar | | operator | enum | | right_operand | varchar | +---------------+---------+ 在 SQL 中,(left_operand, operator, right_operand) 是该表主键. 该表包含了需要计算的布尔表达式. operator 是枚举类型, 取值于('<', '>', '=') left_operand 和 right_operand 的值保证存在于 Variables 表单中.
计算表 Expressions 中的布尔表达式。 返回的结果表 无顺序要求 。
1 2 3
select left_operand,operator,right_operand,case when operator='=' then v1.value = v2.value case when operator='>' then v1.value > v2.value case when operator='<' then v1.value < v2.value end value from Expressions e,Variables v1,Variables v2 where e.left_operand = v1.name and e.right_operand = v2.name
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# Write your MySQL query statement below SELECT left_operand, operator, right_operand, CASE WHEN ( (operator = '=' AND v1.value = v2.value) OR (operator = '>' AND v1.value > v2.value) OR (operator = '<' AND v1.value < v2.value) ) THEN 'true' ELSE 'false' END AS value FROM Expressions AS e JOIN Variables AS v1 ON e.left_operand = v1.name JOIN Variables AS v2 ON e.right_operand = v2.name;
表 Accounts: +---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | name | varchar | +---------------+---------+ id 是该表主键(具有唯一值的列) 该表包含账户 id 和账户的用户名.
表 Logins: +---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | login_date | date | +---------------+---------+ 该表可能包含重复项. 该表包含登录用户的账户 id 和登录日期. 用户也许一天内登录多次. 活跃用户 是指那些至少连续 5 天登录账户的用户。 编写解决方案, 找到 活跃用户 的 id 和 name。 返回的结果表按照 id 排序 。
# Write your MySQL query statement below WITH T AS ( SELECT DISTINCT * FROM Logins JOIN Accounts USING (id) ), P AS ( SELECT *, DATE_SUB( login_date, INTERVAL ROW_NUMBER() OVER ( PARTITION BY id ORDER BY login_date ) DAY ) g FROM T ) SELECT DISTINCT id, name FROM P GROUP BY id, g HAVING COUNT(*) >= 5 ORDER BY 1;
# Write your MySQL query statement below SELECT item_category AS c2ategory, SUM(IF(DAYOFWEEK(order_date) = '2', quantity, 0)) AS Monday, SUM(IF(DAYOFWEEK(order_date) = '3', quantity, 0)) AS Tuesday, SUM(IF(DAYOFWEEK(order_date) = '4', quantity, 0)) AS Wednesday, SUM(IF(DAYOFWEEK(order_date) = '5', quantity, 0)) AS Thursday, SUM(IF(DAYOFWEEK(order_date) = '6', quantity, 0)) AS Friday, SUM(IF(DAYOFWEEK(order_date) = '7', quantity, 0)) AS Saturday, SUM(IF(DAYOFWEEK(order_date) = '1', quantity, 0)) AS Sunday FROM Orders AS o RIGHT JOIN Items AS i ON o.item_id = i.item_id GROUP BY category ORDER BY category
1
这里把if换成case when也可以,注意case when then ... when then ... end 和case when then end,case when then end的不同
select sell_date, count(distinct product) as num_sold, group_concat(distinct product order by product separator ',') as products from Activities group by sell_date order by sell_date
1517.查找拥有有效邮箱的用户 regexp REGEXP_LIKE 正则表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
表: Users +---------------+---------+ | Column Name | Type | +---------------+---------+ | user_id | int | | name | varchar | | mail | varchar | +---------------+---------+ user_id 是该表的主键(具有唯一值的列)。 该表包含了网站已注册用户的信息。有一些电子邮件是无效的。 编写一个解决方案,以查找具有有效电子邮件的用户。 一个有效的电子邮件具有前缀名称和域,其中:
# Write your MySQL query statement below WITH RECURSIVE t AS ( SELECT 1 AS n UNION ALL SELECT n + 1 FROM t WHERE n < 100 ) SELECT n AS ids FROM t WHERE n < ( SELECT MAX(customer_id) FROM Customers ) AND n NOT IN ( SELECT customer_id FROM Customers );
# Write your MySQL query statement below WITH recursive Months AS ( SELECT 1 AS month UNION ALL SELECT month + 1 FROM Months WHERE month < 12 ), Ride AS ( SELECT MONTH(requested_at) AS month, COUNT(1) AS cnt FROM Rides AS r JOIN AcceptedRides AS a ON r.ride_id = a.ride_id AND YEAR(requested_at) = 2020 GROUP BY month )
SELECT m.month, COUNT(driver_id) AS active_drivers, IFNULL(r.cnt, 0) AS accepted_rides FROM Months AS m LEFT JOIN Drivers AS d ON (m.month >= MONTH(d.join_date) AND YEAR(d.join_date) = 2020) OR YEAR(d.join_date) < 2020 LEFT JOIN Ride AS r ON m.month = r.month GROUP BY month;
# Write your MySQL query statement below WITH RECURSIVE Months AS ( SELECT 1 AS month UNION ALL SELECT month + 1 FROM Months WHERE month < 12 ), Ride AS ( SELECT month, SUM(IFNULL(ride_distance, 0)) AS ride_distance, SUM(IFNULL(ride_duration, 0)) AS ride_duration FROM Months AS m LEFT JOIN Rides AS r ON month = MONTH(requested_at) AND YEAR(requested_at) = 2020 LEFT JOIN AcceptedRides AS a ON r.ride_id = a.ride_id GROUP BY month ) SELECT month, ROUND( AVG(ride_distance) OVER (ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING), 2 ) AS average_ride_distance, ROUND( AVG(ride_duration) OVER (ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING), 2 ) AS average_ride_duration FROM Ride ORDER BY month LIMIT 10;
with cte1 as ( #先全部小写处理 select user_id, lower(name) as name from Users) #首字母改成大写和字符串剩下部分进行拼接 select user_id, concat( case substring(name,1,1) when "a" then "A" when "b" then "B" when "c" then "C" when "d" then "D" when "e" then "E" when "f" then "F" when "g" then "G" when "h" then "H" when "i" then "I" when "j" then "J" when "k" then "K" when "l" then "L" when "m" then "M" when "n" then "N" when "o" then "O" when "p" then "P" when "q" then "Q" when "r" then "R" when "s" then "S" when "t" then "T" when "u" then "U" when "v" then "V" when "w" then "W" when "x" then "X" when "y" then "Y" when "z" then "Z" end , substring(name,2)) as name from cte1 order by user_id;
1 2 3 4
select user_id, concat(upper(left(name, 1)), lower(right(name, length(name) - 1))) name from Users order by user_id
1683.无效的推文
1 2 3 4 5 6 7 8 9 10 11 12 13 14
表:Tweets +----------------+---------+ | Column Name | Type | +----------------+---------+ | tweet_id | int | | content | varchar | +----------------+---------+ 在 SQL 中,tweet_id 是这个表的主键。 content 只包含字母数字字符,'!',' ',不包含其它特殊字符。 这个表包含某社交媒体 App 中所有的推文。
查询所有无效推文的编号(ID)。当推文内容中的字符数严格大于 15 时,该推文是无效的。
以任意顺序返回结果表。
1 2 3 4 5
# Write your MySQL query statement below SELECT tweet_id FROM Tweets WHERE CHAR_LENGTH(content) > 15;
1709.访问日期之间最大的空档期 LEAD(xxx) OVER(partition by)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
表: UserVisits +-------------+------+ | Column Name | Type | +-------------+------+ | user_id | int | | visit_date | date | +-------------+------+ 该表没有主键,它可能有重复的行 该表包含用户访问某特定零售商的日期日志。 假设今天的日期是 '2021-1-1' 。
with t as( select user_id,visit_date,row_number() over(partition by user_id order by visit_date) rk from UserVisits )
with s as( select t1.user_id user_id,max(t2.visit_date-t1.visit_date) biggest_window from t t1 join t t2 on t1.user_id = t2.user_id and t2.rk - t1.rk = 1 group by t1.user_id order by user_id )
select * from s union all select user_id,datediff('2021-1-1',visit_date) biggest_window from UserVisits where user_id not in select user_id from s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# Write your MySQL query statement below WITH T AS ( SELECT user_id, DATEDIFF( LEAD(visit_date, 1, '2021-1-1') OVER ( PARTITION BY user_id ORDER BY visit_date ), visit_date ) AS diff FROM UserVisits ) SELECT user_id, MAX(diff) AS biggest_window FROM T GROUP BY 1 ORDER BY 1;
--MySQL with temp as (select * from calls union all select recipient_id caller_id, caller_id recipient_id, call_time from calls ),
temp1 as (select *, dense_rank() over (partition by date_format(call_time,"%Y-%m-%d"),caller_id order by call_time asc) rk1, dense_rank() over (partition by date_format(call_time,"%Y-%m-%d"),caller_id order by call_time desc) rk2 from temp )
select distinct caller_id as user_id from temp1 where rk1 = 1 or rk2 = 1 group by caller_id, date_format(call_time,"%Y-%m-%d") having count(distinct recipient_id) = 1
with t1 as (select caller_id,recipient_id,call_time #选出 所有id 在某个时间 跟另一个通话的id from Calls union all select recipient_id,caller_id,call_time from Calls ), t2 as ( select#按 caller_id 和 每天 分组 对 call_time标号 便于 找到 每天 第一个 和最后的一通电话 caller_id,recipient_id,call_time,row_number() over(partition by caller_id,date_format(call_time,'%Y-%m-%d') order by call_time) rn,row_number() over(partition by caller_id,date_format(call_time,'%Y-%m-%d') order by call_time desc) rn2 from t1 ), t3 as ( select caller_id,recipient_id,date_format(call_time,'%Y-%m-%d') day #某天第一次通话 from t2 where rn = 1 union all select caller_id,recipient_id,date_format(call_time,'%Y-%m-%d') day#某天最后一次通话 from t2 where rn2 = 1 ) select distinct caller_id user_id from t3 group by caller_id,day #对 某人某天第一次 和最后一次通话的id 去重计数 值为1就是题中需求 having count(distinct recipient_id)=1
-- https://leetcode.cn/problems/count-the-number-of-experiments drop table if EXISTS Experiments; Create table If Not Exists Experiments (experiment_id int, platform enum('Android','IOS','Web'), experiment_name enum('Programming','Sports','Reading')); insert into Experiments values (4,'IOS','Programming'); insert into Experiments values (13,'IOS','Sports'); insert into Experiments values (14,'Android','Reading'); insert into Experiments values (8,'Web','Reading'); insert into Experiments values (12,'Web','Reading'); insert into Experiments values (18,'Web','Programming'); select * from Experiments;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
with pe as ( select * from ( select 'IOS' platform union all select 'Android' platform union all select 'Web' platform )p cross join ( select 'Programming' experiment_name union all select 'Sports' experiment_name union all select 'Reading' experiment_name )e ) -- select * from pe; select pe.platform,pe.experiment_name,count(w.platform) as num_experiments from pe left join Experiments as w using(platform,experiment_name) group by platform,experiment_name;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# Write your MySQL query statement below with new_table as( select 'Android' platform union select 'IOS' union select 'Web' ), other_table as( select 'Reading' experiment_name union select 'Sports' union select 'Programming' ) select new_table.platform ,other_table.experiment_name,count(experiment_id)num_experiments from new_table join other_table #笛卡尔积 left join Experiments E on E.platform = new_table.platform AND other_table.experiment_name = E.experiment_name group by new_table.platform ,other_table.experiment_name
with t1 as (select employee_id,experience,salary,sum(salary) over(partition by experience order by salary rows between unbounded preceding and current row) so #按 experience 分组开窗,按salary 生序排列逐一求和 然后 <=70000 就是能招聘的 员工 from Candidates ), t2 as ( select "Senior" experience,count(employee_id) accepted_candidates,70000-ifnull(max(so),0) m # 能招聘的 Senior 等级员工 from t1 where experience = "Senior" and so<=70000 ) select experience,accepted_candidates from t2 union all #上下两表拼接 就是题中需求 select "Junior" experience,count(employee_id) accepted_candidates # 能招聘的 Junior 等级员工 from t1 where experience = "Junior" and so<=(select m from t2)
# Write your MySQL query statement below with new_table as( select DISTINCT account_id from Subscriptions where date_format(start_date,'%Y') = '2021' or date_format(end_date,'%Y') = '2021' ) select count(*) accounts_count from Streams S right join new_table N on N.account_id = S.account_id where substring(stream_date,1,4) <> '2021'
1
用year函数,or, not in,子查询就可以了
2026 简单
1
简单 但我只想到了select是算出比率,然后再select
1 2 3 4 5 6
# Write your MySQL query statement below SELECT problem_id FROM Problems #这里不要用round四舍五入 WHERE likes/(likes+dislikes)<0.60 order by problem_id asc
2041 简单
1
简单
2051
1 2 3 4 5 6 7 8 9 10 11 12 13
# Write your MySQL query statement below select M.member_id,M.name,( case when count(V.visit_id) = 0 then 'Bronze' when count(P.visit_id)/count(V.visit_id) < 0.5 then 'Silver' when count(P.visit_id)/count(V.visit_id) <0.8 then 'Gold' else 'Diamond' end) AS category from Members M left join Visits V on M.member_id = V.member_id left join Purchases P on P.visit_id = V.visit_id group by M.member_id
# Write your MySQL query statement below SELECT account_id, day, SUM(IF(type = 'Deposit', amount, -amount)) OVER ( PARTITION BY account_id ORDER BY day ) AS balance FROM Transactions ORDER BY 1, 2;
表: NewYork +-------------+------+ | Column Name | Type | +-------------+------+ | student_id | int | | score | int | +-------------+------+ 在 SQL 中,student_id 是这个表的主键。 每一行包含纽约大学 (New York University) 中一名学生一次考试的成绩。 表: California +-------------+------+ | Column Name | Type | +-------------+------+ | student_id | int | | score | int | +-------------+------+ 在 SQL 中,student_id 是这个表的主键。 每一行包含加州大学 (California University) 中一名学生一次考试的成绩。 纽约大学和加州大学之间举行了一场比赛。这场比赛由两所大学中相同数量的学生参加。拥有更多优秀学生的大学赢得这场比赛。如果两所大学的优秀学生数量相同,则这场比赛平局。 优秀学生是指在考试中获得 90% 或更高成绩的学生。 返回:
"New York University" 若纽约大学赢得这场比赛。 "California University" 若加州大学赢得这场比赛。 "No Winner" 若这场比赛平局。
1 2 3 4 5 6 7 8 9 10
# Write your MySQL query statement below SELECT CASE WHEN n1.cnt > n2.cnt THEN 'New York University' WHEN n1.cnt < n2.cnt THEN 'California University' ELSE 'No Winner' END AS winner FROM (SELECT COUNT(1) AS cnt FROM NewYork WHERE score >= 90) AS n1, (SELECT COUNT(1) AS cnt FROM California WHERE score >= 90) AS n2;
1 2 3 4 5 6 7 8
select case when n1>n2 then 'NewYork' when n1<n2 then 'California' else 'No Winner' end AS winner ( select count(1) n1,(select count(1) from California where score>=90) n2 from NewYork where score>=90 ) t
2084.为订单类型为 0的客户删除类型为 1的订单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
活动表: Orders +-------------+------+ | Column Name | Type | +-------------+------+ | order_id | int | | customer_id | int | | order_type | int | +-------------+------+ order_id是此表的主键列。 此表的每一行都表示订单的ID、订购该订单的客户的ID以及订单类型。 订单可以是类型0或类型1。
# Write your MySQL query statement below WITH T AS ( SELECT DISTINCT customer_id FROM Orders WHERE order_type = 0 ) SELECT * FROM Orders AS o WHERE order_type = 0 OR NOT EXISTS (SELECT 1 FROM T AS t WHERE t.customer_id = o.customer_id);
1 2 3 4 5 6 7 8 9
WITH T AS ( SELECT DISTINCT customer_id FROM Orders WHERE order_type = 0 ) SELECT * FROM Orders AS o WHERE order_type = 0 OR customer_id NOT IN (SELECT * FROM T);
表: Terms +-------------+------+ | Column Name | Type | +-------------+------+ | power | int | | factor | int | +-------------+------+ power 是该表具有唯一值的列。 该表的每一行包含关于方程的一项的信息。 power 是范围为 [0, 100] 的整数。 factor 是范围为 [-100,100] 的整数,且不能为零。 你有一个非常强大的程序,可以解决世界上任何单变量的方程。传递给程序的方程必须格式化如下:
# Write your MySQL query statement below WITH T AS ( SELECT power, CASE power WHEN 0 THEN IF(factor > 0, CONCAT('+', factor), factor) WHEN 1 THEN CONCAT( IF(factor > 0, CONCAT('+', factor), factor), 'X' ) ELSE CONCAT( IF(factor > 0, CONCAT('+', factor), factor), 'X^', power ) END AS it FROM Terms ) SELECT CONCAT(GROUP_CONCAT(it ORDER BY power DESC SEPARATOR ""), '=0') AS equation FROM T;
用游标应该很简单 set @s = ''; declare my_cursor cursor for select power,factor from Terms order by power desc; open my_cursor; fetch my_cursor into @power,@factor while @@fetch_status=0 do if @facter > 0 then set @facter = concat("+",@facter) end if if @power = 0 then set @power = @facter else if @power = 1 then set @power = concat(@facter,'X') else if @power > 1 then set @power = concat(@facter,'X^',@power) end if set @s=concat(@s,@power) fetch my_cursor into @power,@factor end while close my_cursor; select
# Write your MySQL query statement below SELECT bus_id, COUNT(passenger_id) - LAG(COUNT(passenger_id), 1, 0) OVER ( ORDER BY b.arrival_time ) AS passengers_cnt FROM Buses AS b LEFT JOIN Passengers AS p ON p.arrival_time <= b.arrival_time GROUP BY 1 ORDER BY 1;
declare my_cursor cursor for select bus_id,capacity,count(1) num from Buses b inner join Passengers p on b.arrival_time >= p.arrival_time group by bus_id order by b.arrival_time
open my_cursor; set @sum=0; fetch my_cursor into @bus_id,@capacity,@num; while @@fetch_status=0 do @v=@num-@sum if @v=0 then @people=0; else if @capacity>=@v then @people=@v; else then @people=@capacity; end if select @bus_id,@people; fetch my_cursor into @bus_id,@capacity,@num; end while
# Write your MySQL query statement below SELECT CONCAT('#', SUBSTRING_INDEX(SUBSTRING_INDEX(tweet, '#', -1), ' ', 1)) AS hashtag, COUNT(1) AS hashtag_count FROM Tweets WHERE DATE_FORMAT(tweet_date, '%Y%m') = '202402' GROUP BY 1 ORDER BY 2 DESC, 1 DESC LIMIT 3;
# Write your MySQL query statement below WITH P AS ( SELECT p1.user_id AS user_id, COUNT(1) AS cnt FROM Posts AS p1 JOIN Posts AS p2 ON p1.user_id = p2.user_id AND p2.post_date BETWEEN p1.post_date AND DATE_ADD(p1.post_date, INTERVAL 6 DAY) GROUP BY p1.user_id, p1.post_id ), T AS ( SELECT user_id, COUNT(1) / 4 AS avg_weekly_posts FROM Posts WHERE post_date BETWEEN '2024-02-01' AND '2024-02-28' GROUP BY 1 ) SELECT user_id, MAX(cnt) AS max_7day_posts, avg_weekly_posts FROM P JOIN T USING (user_id) GROUP BY 1 HAVING max_7day_posts >= avg_weekly_posts * 2 ORDER BY 1;
select floor(sum(TIMESTAMPDIFF(SECOND,s2.status_time,s1.status_time))/86400) total_uptime_days from Servers s1,(select *,row_number() over(order by server_id) rk from Servers) s2 where s1.session_status = 'start' and s1.rk +1 = s2.rk and s2.session_status = 'stop'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# Write your MySQL query statement below WITH T AS ( SELECT session_status, status_time, LEAD(status_time) OVER ( PARTITION BY server_id ORDER BY status_time ) AS next_status_time FROM Servers ) SELECT FLOOR(SUM(TIMESTAMPDIFF(SECOND, status_time, next_status_time)) / 86400) AS total_uptime_days FROM T WHERE session_status = 'start';
with t as ( select seat_id,seat_id-rk s from ( select *,row_number() over(order by seat_id) rk from Cinema where free = 1) t ),p as ( select min(seat_id) first_seat_id,max(seat_id) last_seat_id,count(1) consecutive_seats_len,dense_rank() over(order by count(1) desc) rk from t group by s )
select first_seat_id, last_seat_id, consecutive_seats_len from p where rk=1
# Write your MySQL query statement below WITH T AS ( SELECT *, seat_id - (RANK() OVER (ORDER BY seat_id)) AS gid FROM Cinema WHERE free = 1 ), P AS ( SELECT MIN(seat_id) AS first_seat_id, MAX(seat_id) AS last_seat_id, COUNT(1) AS consecutive_seats_len, RANK() OVER (ORDER BY COUNT(1) DESC) AS rk FROM T GROUP BY gid ) SELECT first_seat_id, last_seat_id, consecutive_seats_len FROM P WHERE rk = 1 ORDER BY 1;
查询结果格式如下所示: 示例: 输入: Tweets 表: +----------+-----------------------------------------------------------------------------------+ | tweet_id | content | +----------+-----------------------------------------------------------------------------------+ | 1 | Traveling, exploring, and living my best life @JaneSmith @SaraJohnson @LisaTaylor | | | @MikeBrown #Foodie #Fitness #Learning | | 2 | Just had the best dinner with friends! #Foodie #Friends #Fun | | 4 | Working hard on my new project #Work #Goals #Productivity #Fun | +----------+-----------------------------------------------------------------------------------+ 输出: +----------+ | tweet_id | +----------+ | 1 | | 4 | +----------+
1 2 3 4 5 6 7 8
# Write your MySQL query statement below SELECT tweet_id FROM Tweets WHERE LENGTH(content) > 140 OR (LENGTH(content) - LENGTH(REPLACE(content, '@', ''))) > 3 OR (LENGTH(content) - LENGTH(REPLACE(content, '#', ''))) > 3 ORDER BY 1;
SELECT t1.employee_id, COUNT(*) AS overlapping_shifts FROM EmployeeShifts t1 JOIN EmployeeShifts t2 ON t1.employee_id = t2.employee_id AND t1.start_time < t2.start_time AND t1.end_time > t2.start_time GROUP BY 1 HAVING overlapping_shifts > 0 ORDER BY 1;
WITH S AS ( SELECT candidate_id, project_id, COUNT(*) matched_skills, SUM( CASE WHEN proficiency > importance THEN 10 WHEN proficiency < importance THEN -5 ELSE 0 END ) + 100 AS score FROM Candidates JOIN Projects USING (skill) GROUP BY 1, 2 ), T AS ( SELECT project_id, COUNT(1) required_skills FROM Projects GROUP BY 1 ), P AS ( SELECT project_id, candidate_id, score, RANK() OVER ( PARTITION BY project_id ORDER BY score DESC, candidate_id ) rk FROM S JOIN T USING (project_id) WHERE matched_skills = required_skills ) SELECT project_id, candidate_id, score FROM P WHERE rk = 1 ORDER BY 1;
1 2 3 4 5
#### 3328.查找每个州的城市 I I group_concat
表:cities +————-+———+ | Column Name | Type | +————-+———+ | state | varchar | | city | varchar | +————-+———+ (state, city) 是这张表中值互不相同的列的组合。 这张表的每一行包含州名和其中的城市名。 编写一个解决方案来找到 每个州 中的 所有城市 并且根据下列条件分析它们:
示例: 输入: cities 表: +————–+—————+ | state | city | +————–+—————+ | New York | New York City | | New York | Newark | | New York | Buffalo | | New York | Rochester | | California | San Francisco | | California | Sacramento | | California | San Diego | | California | Los Angeles | | Texas | Tyler | | Texas | Temple | | Texas | Taylor | | Texas | Dallas | | Pennsylvania | Philadelphia | | Pennsylvania | Pittsburgh | | Pennsylvania | Pottstown | +————–+—————+ 输出: +————-+——————————————-+———————–+ | state | cities | matching_letter_count | +————-+——————————————-+———————–+ | Pennsylvania| Philadelphia, Pittsburgh, Pottstown | 3 | | Texas | Dallas, Taylor, Temple, Tyler | 3 | | New York | Buffalo, Newark, New York City, Rochester | 2 | +————-+——————————————-+———————–+
1
Write your MySQL query statement below
SELECT state, GROUP_CONCAT(city ORDER BY city SEPARATOR ‘, ‘) AS cities, COUNT( CASE WHEN LEFT(city, 1) = LEFT(state, 1) THEN 1 END ) AS matching_letter_count FROM cities GROUP BY 1 HAVING COUNT(city) >= 3 AND matching_letter_count > 0 ORDER BY 3 DESC, 1;
1 2 3 4 5
#### 3368.首字母大写 recursive
表:user_content +————-+———+ | Column Name | Type | +————-+———+ | content_id | int | | content_text| varchar | +————-+———+ content_id 是这张表的唯一主键。 每一行包含一个不同的 ID 以及对应的文本内容。 编写一个解决方案来通过应用以下规则来转换 content_text 列中的文本:
示例: 输入: user_content 表: +————+———————————–+ | content_id | content_text | +————+———————————–+ | 1 | hello world of Sql | | 2 | the QUICK brown fox | | 3 | data science AND machine learning | | 4 | TOP rated programming BOOKS | +————+———————————–+ 输出: +————+———————————–+———————————–+ | content_id | original_text | converted_text | +————+———————————–+———————————–+ | 1 | hello world of Sql | Hello World Of Sql | | 2 | the QUICK brown fox | The Quick Brown Fox | | 3 | data science AND machine learning | Data Science And Machine Learning | | 4 | TOP rated programming BOOKS | Top Rated Programming Books | +————+———————————–+———————————–+
1
WITH RECURSIVE capitalized_words AS ( SELECT content_id, content_text, SUBSTRING_INDEX(content_text, ‘ ‘, 1) AS word, SUBSTRING( content_text, LENGTH(SUBSTRING_INDEX(content_text, ‘ ‘, 1)) + 2 ) AS remaining_text, CONCAT( UPPER(LEFT(SUBSTRING_INDEX(content_text, ‘ ‘, 1), 1)), LOWER(SUBSTRING(SUBSTRING_INDEX(content_text, ‘ ‘, 1), 2)) ) AS processed_word FROM user_content UNION ALL SELECT c.content_id, c.content_text, SUBSTRING_INDEX(c.remaining_text, ‘ ‘, 1), SUBSTRING(c.remaining_text, LENGTH(SUBSTRING_INDEX(c.remaining_text, ‘ ‘, 1)) + 2), CONCAT( c.processed_word, ‘ ‘, CONCAT( UPPER(LEFT(SUBSTRING_INDEX(c.remaining_text, ‘ ‘, 1), 1)), LOWER(SUBSTRING(SUBSTRING_INDEX(c.remaining_text, ‘ ‘, 1), 2)) ) ) FROM capitalized_words c WHERE c.remaining_text != ‘’ ) SELECT content_id, content_text AS original_text, MAX(processed_word) AS converted_text FROM capitalized_words GROUP BY 1, 2;
1 2 3
#### 3374.首字母大写II recursive
表:user_content +————-+———+ | Column Name | Type | +————-+———+ | content_id | int | | content_text| varchar | +————-+———+ content_id 是这张表的唯一主键。 每一行包含一个不同的 ID 以及对应的文本内容。 编写一个解决方案来根据下面的规则来转换 content_text 列中的文本:
示例: 输入: user_content 表: +————+———————————+ | content_id | content_text | +————+———————————+ | 1 | hello world of SQL | | 2 | the QUICK-brown fox | | 3 | modern-day DATA science | | 4 | web-based FRONT-end development | +————+———————————+ 输出: +————+———————————+———————————+ | content_id | original_text | converted_text | +————+———————————+———————————+ | 1 | hello world of SQL | Hello World Of Sql | | 2 | the QUICK-brown fox | The Quick-Brown Fox | | 3 | modern-day DATA science | Modern-Day Data Science | | 4 | web-based FRONT-end development | Web-Based Front-End Development | +————+———————————+———————————+
1
with recursive cte as( select content_id, content_text ‘original_text’, case when instr(substring_index(content_text,’ ‘,1),’-‘)>0 then upper(substring_index(content_text,’ ‘,1)) else concat(upper(left(substring_index(content_text,’ ‘,1),1)), lower(substring(substring_index(content_text,’ ‘,1),2))) end processed_w, substring(content_text,length(substring_index(content_text,’ ‘,1))+2) remainStr from user_content union all select content_id, content_text, concat(processed_w,’ ‘, case when instr(substring_index(remainStr,’ ‘,1),’-‘)>0 then upper(substring_index(remainStr,’ ‘,1)) else concat(upper(left(substring_index(remainStr,’ ‘,1),1)), lower(substring(substring_index(remainStr,’ ‘,1),2))) end ), substring(remainStr,length(substring_index(remainStr,’ ‘,1))+2) remainStr from cte where remain!=’’ )
select content_id,original_text,max(processed_w) converted_text from cte group by content_id
1 2 3 4 5
#### 难 3390.最长团队传球连击
表:Teams +————-+———+ | Column Name | Type | +————-+———+ | player_id | int | | team_name | varchar | +————-+———+ player_id 是这张表的唯一主键。 每行包含队员的唯一标识符以及在该场比赛中参赛的某支队伍的名称。
表:Passes +————-+———+ | Column Name | Type | +————-+———+ | pass_from | int | | time_stamp | varchar | | pass_to | int | +————-+———+ (pass_from, time_stamp) 是这张表的唯一主键。 pass_from 是 Teams 表中 player_id 的外键。 每一行代表比赛中的一次传球,time_stamp 表示传球发生的分钟时间(00:00-90:00)。 pass_to 是接收传球队员的 player_id。 编写一个解决方案以找到比赛中 每个队伍 的 最长连续成功传球。规则如下:
~~~. with recursive cte as( select giver_id,receiver_id,gift_value,giver_id start_id from SecretSanta union all select SecretSanta.giver_id,SecretSanta.receiver_id,SecretSanta.gift_value gift_value,cte.start_id from SecretSanta inner join cte on cte.receiver_id = SecretSanta.giver_id and cte.start_id != SecretSanta.receiver_id )
select distinct count(*) chain_length,sum(gift_value) total_gift_value from cte group by start_id
WITH RECURSIVE cte AS ( SELECT giver_id, receiver_id, gift_value, giver_id AS start, giver_id AS min_id, gift_value AS total_value, 1 AS length FROM SecretSanta UNION ALL SELECT s.giver_id, s.receiver_id, s.gift_value, cte.start, LEAST(cte.min_id, s.giver_id) AS min_id, cte.total_value + s.gift_value AS total_value, cte.length + 1 AS length FROM cte JOIN SecretSanta s ON cte.receiver_id = s.giver_id WHERE cte.receiver_id <> cte.start ), rings AS ( SELECT min_id AS original_chain_id, length AS chain_length, total_value AS total_gift_value FROM cte WHERE receiver_id = start AND start = min_id ) SELECT ROW_NUMBER() OVER (ORDER BY chain_length DESC, total_gift_value DESC) AS chain_id, chain_length, total_gift_value FROM rings ORDER BY chain_length DESC, total_gift_value DESC;
3415.查找具有三个连续数字的产品 regexp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
表:Products
+-------------+---------+ | Column Name | Type | +-------------+---------+ | product_id | int | | name | varchar | +-------------+---------+ product_id 是这张表的唯一主键。 这张表的每一行包含产品的 ID 和名字。 编写一个解决方案来找到所有名字中包含 三位连续数字 且无连续三位以上数字的所有 产品。
返回结果表以 product_id 升序 排序。
结果格式如下所示。
1 2 3 4 5
# Write your MySQL query statement below SELECT product_id, name FROM Products WHERE name REGEXP '(^|[^0-9])[0-9]{3}([^0-9]|$)' ORDER BY 1;
1 2 3 4 5
select * from Products where str regexp '[^0-9][0-9]{3}[^0-9]' -- 匹配 %123% or str regexp '[^0-9][0-9]{3}$' -- 匹配 %123 or str regexp '^[0-9]{3}[^0-9]' -- 匹配 123%
with rk as ( select *, rank() over(partition by student_id,subject order by exam_date) r1, rank() over(partition by student_id,subject order by exam_date desc) r2 from Scores ) select a.student_id, a.subject, a.score first_score, b.score latest_score from rk a join rk b on a.student_id=b.student_id and a.subject=b.subject and a.r1=1 and b.r2=1 and a.r1!=a.r2 and a.score<b.score
1
先筛选出一门学科至少参加过两次的人,对这些人的这些学科再按照上面那样做也可以
3436.查找合法邮箱 regexp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
表:Users
+-----------------+---------+ | Column Name | Type | +-----------------+---------+ | user_id | int | | email | varchar | +-----------------+---------+ (user_id) 是这张表的唯一主键。 每一行包含用户的唯一 ID 和邮箱地址。 编写一个解决方案来查找所有 合法邮箱地址。一个合法的邮箱地址符合下述条件:
select ip, count(*) as invalid_count from logs WHERE ip like "%.0%" or ip like "0%" or length(ip) - length(replace(ip, '.', '')) != 3 or CAST(substring_index(ip, ".", 1) AS UNSIGNED)>255 or CAST(substring_index(substring_index(ip, ".", 2), ".", -1) AS UNSIGNED) >255 or CAST(substring_index(substring_index(ip, ".", 3), ".", -1) AS UNSIGNED) >255 or CAST(substring_index(ip, ".", -1) AS UNSIGNED) >255 GROUP BY ip ORDER BY invalid_count DESC, ip DESC;
SELECT ip, count(ip) as invalid_count FROM logs WHERE ip not REGEXP '^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])$' group by ip order by invalid_count desc, ip desc
# Write your MySQL query statement below SELECT sample_id, dna_sequence, species, dna_sequence LIKE 'ATG%' AS has_start, dna_sequence REGEXP 'TAA$|TAG$|TGA$' AS has_stop, dna_sequence LIKE '%ATAT%' AS has_atat, dna_sequence REGEXP 'GGG+' AS has_ggg FROM Samples ORDER BY 1;
1 2 3 4 5 6
select *, left(dna_sequence,3)='ATG' has_start, right(dna_sequence,3) in ('TAA','TAG','TGA') has_stop, dna_sequence like '%ATAT%' has_atat, instr(dna_sequence,'GGG')>0 has_ggg from Samples
1 2 3 4
CASE WHEN regexp_like(dna_sequence, '^ATG') THEN 1 ELSE 0 END has_start, CASE WHEN regexp_like(dna_sequence, '(TAA$|TAG$|TGA$)') THEN 1 ELSE 0 END has_stop, CASE WHEN regexp_like(dna_sequence, 'ATAT') THEN 1 ELSE 0 END has_atat, CASE WHEN regexp_like(dna_sequence, 'G{3}') THEN 1 ELSE 0 END has_ggg
WITH RECURSIVE cte (employee_id, employee_name, salary, level, label) AS ( SELECT employee_id, employee_name, salary, 1, concat(employee_id) FROM Employees WHERE manager_id IS NULL UNION all SELECT e.employee_id, e.employee_name, e.salary, level + 1, concat(label, ',', e.employee_id) FROM Employees e JOIN cte ON e.manager_id = cte.employee_id )
SELECT c.employee_id, c.employee_name, c.level, count(1) - 1 team_size, sum(c1.salary) budget FROM cte c JOIN cte c1 ON c1.label REGEXP concat('^', c.label, '\\b') GROUP BY c.employee_id ORDER BY c.level, budget DESC, c.employee_name
with recursive EmployeeTree as ( select *, 1 as level from Employees where manager_id is null union all select e.*, et.level + 1 as level from Employees e join EmployeeTree et on et.employee_id = e.manager_id ), AllSubsident as ( select employee_id as employee_id, employee_id as subsident_id, salary from Employees union all select a.employee_id, e.employee_id as subsident_id, e.salary from Employees e join AllSubsident a on a.subsident_id = e.manager_id ), grouped as ( select employee_id, count(subsident_id) - 1 as team_size, sum(salary) as budget from AllSubsident group by employee_id order by employee_id ) select g.employee_id, e.employee_name, e.level, g.team_size, g.budget from grouped g join EmployeeTree e on g.employee_id = e.employee_id order by e.level,g.budget desc,e.employee_name;
# Write your MySQL query statement below WITH user_category AS ( SELECT DISTINCT user_id, category FROM ProductPurchases JOIN ProductInfo USING (product_id) ), pair_per_user AS ( SELECT a.user_id, a.category AS category1, b.category AS category2 FROM user_category AS a JOIN user_category AS b ON a.user_id = b.user_id AND a.category < b.category ) SELECT category1, category2, COUNT(DISTINCT user_id) AS customer_count FROM pair_per_user GROUP BY 1, 2 HAVING customer_count >= 3 ORDER BY 3 DESC, 1, 2;
with details as ( select , case when month(sale_date) in ('12','1','2') then 'Winter' when month(sale_date) in ('3','4','5') then 'Spring' when month(sale_date) in ('6','7','8') then 'Summer' when month(sale_date) in ('9','10','11') then 'Fall' end as season from sales ), group_details as (select a.season,b.category, sum(quantity) as total_quantity, sum(quantityprice) as total_revenue, row_number() over(partition by a.season order by sum(quantity) desc,sum(quantityprice) desc) rn from details a left join products b on a.product_id = b.product_id group by a.season,b.category) select season,category, total_quantity,total_revenue from group_details where rn=1
with t as ( select *, case when month(sale_date) between 3 and 5 then "Spring" when month(sale_date) between 6 and 8 then "Summer" when month(sale_date) between 9 and 11 then "Fall" else "Winter" end as "season" from sales ),t2 as ( select sum(quantity * price) "total_revenue", season,category,sum(quantity) as "total_quantity", rank()over(partition by season order by sum(quantity) desc,sum(quantity * price) desc) as rk from t join products p using(product_id) group by season,category ) select season,category,total_quantity,total_revenue from t2 where rk = 1 order by season
######### with t as ( select *, case when month(sale_date) between 3 and 5 then "Spring" when month(sale_date) between 6 and 8 then "Summer" when month(sale_date) between 9 and 11 then "Fall" else "Winter" end as "season" from sales ),t2 as ( select sum(quantity * price)over(partition by season,category) as "total_revenue", season,category,sum(quantity)over(partition by season,category) as "total_quantity" from t join products p using(product_id) ),t3 as ( select *,rank()over(partition by season order by total_quantity desc,total_revenue desc) as rk from t2 ) select distinct season,category,total_quantity,total_revenue from t3 where rk = 1 order by season
WITH temp AS ( SELECT *, Month(sale_date) AS month FROM sales ), get_season AS ( SELECT *, CASE WHEN month in (12,1,2) THEN 'Winter' WHEN month in (3,4,5) THEN 'Spring' WHEN month in (6,7,8) THEN 'Summer' ELSE 'Fall' END AS season FROM temp ), get_cat AS ( SELECT g.product_id, quantity, price, category, season FROM get_season g LEFT JOIN products p ON g.product_id = p.product_id ) ,get_prod_quant AS ( SELECT product_id,season,SUM(quantity) AS total_quantity, SUM(quantity*price) AS total_revenue FROM get_cat GROUP BY category, season ), get_rank AS ( SELECT * FROM ( SELECT *, DENSE_RANK() OVER(PARTITION BY season ORDER BY total_quantity DESC, total_revenue DESC ) rnk FROM get_prod_quant ) tmp WHERE rnk = 1 ), final AS ( SELECT season, category, total_quantity, total_revenue FROM get_rank g LEFT JOIN products p ON g.product_id = p.product_id ORDER BY season )
with t as( select employee_id,review_date,rating,lead(rating,1) over(partition by employee_id order by review_date) lrating from performance_reviews pr where lrating is not null and pr.employee_id in ( select employee_id from performance_reviews p group by employee_id having count(*)>=3 ) )
with p as( select distinct employee_id from( select employee_id,review_date,lrating>rating r from t) s where r=0 )
select y.employee_id,name,max(rating)-min(rating) improvement_score from( select employee_id,review_date,rating,row_number() over(partition by employee_id order by review_date desc) rk from t where t.employee_id not in ( select * from p ) ) y join employees on y.employee_id = employees.employee_id where y.rk <=3 group by y.employee_id
with t as( select patient_id,min(result) result,min(test_date) test_date from covid_tests where result='Positive' group by patient_id )
select covid_tests.patient_id patient_id,patient_name ,age,min(covid_tests.test_date)-t.test_date recovery_time from covid_tests join t on covid_tests.patient_id = t.patient_id and covid_tests.test_date > t.test_date join patients on t.patient_id = patients.patient_id where covid_tests.result = 'Negative' group by covid_tests.patient_id
1. SELECT a.Sid,a.score 01_score,b.score 02_score FROM (SELECT * FROM sc WHERE Cid = 01) AS a,(SELECT * FROM sc WHERE Cid = 02) AS b WHERE a.Sid = b.Sid ;
2. SELECT C1.sid, C3.sname, C3.sage, C3.ssex, C1.score AS score1, C2.score AS score2 FROM (SELECT * FROM SC WHERE Cid = '01') AS C1 INNER JOIN (SELECT * FROM SC WHERE Cid = '02') AS C2 ON C1.sid = C2.sid INNER JOIN Student AS C3 ON C1.sid = C3.sid ;
SELECT * FROM (SELECT * FROM sc WHERE cid = '01') a LEFT JOIN sc ON a.sid = sc.sid AND sc.cid = '02';
---- SELECT * FROM (SELECT * FROM sc WHERE cid = '01') a LEFT JOIN (SELECT * FROM sc WHERE cid = '02') b ON a.sid = b.sid;
--- SELECT * FROM sc a LEFT JOIN sc b ON a.sid = b.sid AND b.cid = '02' WHERE a.cid = '01';
1.3
1 2 3 4 5 6 7 8
查询不存在01课程但存在02课程的学生情况
SELECT * FROM sc s1 WHERE s1.CId='02' AND s1.SId not in ( SELECT s2.SId FROM sc s2 WHERE s2.CId='01');
3 EXISTS
1 2 3 4 5 6 7 8 9
SELECT s.student id,s.name,s.age, s.genderFRoM student s JOIN SC sc ON s.student id= sc.student id
SELECT s.student id,s.name, s.age, s.genderFROM student s WHERE EXISTS( SELECT 1 FROM SC SC WHERE sc.student id=s.student id
7 having的一个使用技巧
1 2 3 4 5 6 7
查询没有学全所有课程的同学的信息
SELECT SC.SId,COUNT(cid) 选课数目 FROM sc GROUP BY sid HAVING 选课数目 < (SELECT COUNT(cid)FROM course c)
8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
查询至少有一门课学号与01的同学所学相同的同学信息
SELECT DISTINCT a.* FROM student a INNER JOIN (SELECT * FROM sc WHERE cid IN (SELECT cid FROM sc WHERE sid = "01")) b ON a.sid = b.sid; ---- SELECT DISTINCT s.* FROM sc INNER JOIN student s ON sc.sid = s.sid WHERE sc.cid IN (SELECT cid FROM sc WHERE sid = "01");
9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
查询和01号同学学习的课程完全相同的其他同学的信息
SELECT SId,COUNT(*) num FROM ( SELECT s1.SId,s1.CId FROM sc s1 INNER JOIN ( SELECT sc.* FROM sc WHERE sc.SId='01') s2 WHERE s1.CId=s2.CId ) t GROUP BY SId HAVING num = (SELECT COUNT(*) FROM sc WHERE sc.SId='01')
13 avg() over(partition by)
1 2 3 4 5 6 7 8 9 10 11 12
按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
SELECT * FROM sc s1 INNER JOIN ( SELECT SId,AVG(score) as avg FROM sc GROUP BY SId ) s2 on s1.SId=s2.SId ORDER BY avg DESC,s1.SId
1 2 3 4 5 6 7 8 9 10 11 12 13
SELECT s.student_name AS 学生姓名, c.course_name AS 课程名称, g.score AS 成绩, AVG(g.score) OVER (PARTITION BY s.student_id) AS 平均成绩 FROM grades g JOIN students s ON g.student_id = s.student_id JOIN courses c ON g.course_id = c.course_id ORDER BY 平均成绩 DESC, s.student_name, c.course_name;
14
1 2 3 4 5 6 7 8 9 10 11 12 13
查询各科成绩最高分、最低分和平均分
SELECT c.course_name AS 课程名称, MAX(g.score) AS 最高分, MIN(g.score) AS 最低分, ROUND(AVG(g.score), 2) AS 平均分 -- 保留两位小数 FROM grades g JOIN courses c ON g.course_id = c.course_id -- 关联课程名称 GROUP BY c.course_id -- 按课程分组(避免课程名重复) ORDER BY c.course_name; -- 按课程名称排序
15 变量的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
按各科成绩进行排名,并显示排名,score重复时继续排序
SELECT sc.* ,DENSE_RANK() over(PARTITION by CId ORDER BY score DESC) r FROM sc
----- 它这个使用变量的方法也不对 如图片 SELECT sid, cid, score, @rank:=@rank+1 as rk FROM sc,(SELECT @rank:=0) as t ORDER BY score DESC; -- 自定义变量 -- # ① 定义变量 set @a:=2 (@用来标识变量),使用变量select @a # ② 定义并使用变量 select @b:=4 # 修改或者重新赋值 select @b:=6
16 dense_rank()、变量的使用
1 2 3 4 5 6 7 8 9
查询学生的总成绩,并进行排名,总分重复时保留名次空缺
SELECT SId,totalscore,DENSE_RANK()over(ORDER BY totalscore DESC) r FROM ( SELECT SId,SUM(score) totalscore FROM sc GROUP BY SId ) t
1 2 3 4 5 6 7
SELECT a.*, @rank:=IF(@sco=sum_score,@rank+0,@rank+1) rk FROM (SELECT sid, SUM(score) sum_score FROM sc GROUP BY sid ORDER BY sum_score DESC) a,(select @sco:=null,@rank:=0) b
SELECT sc.CId 课程编号,c.Cname 课程名称,COUNT(1) 选修人数 ,CONCAT(ROUND(SUM(CASE WHEN sc.score >=0 AND sc.score <= 60 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(0-60]' ,CONCAT(ROUND(SUM(CASE WHEN sc.score >=60 AND sc.score <= 70 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(60-70]' ,CONCAT(ROUND(SUM(CASE WHEN sc.score >= 70 AND sc.score <= 85 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(70-85]' ,CONCAT(ROUND(SUM(CASE WHEN sc.score >= 85 AND sc.score <= 100 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(85-100]' FROM sc LEFT JOIN course c ON sc.cId = c.CId GROUP BY sc.CId,c.Cname
22 like
1 2 3 4 5
查询名字中含有[风]字的学生信息
SELECT * FROM student WHERE sname LIKE '%风%';
25
1 2 3 4
SELECT CId,AVG(score) avg FROM sc GROUP BY CId ORDER BY avg desc,CId
# 法一 SELECT * FROM teacher t LEFT JOIN course c ON t.tid = c.tid LEFT JOIN sc ON c.cid = sc.cid LEFT JOIN student s ON s.sid = sc.sid WHERE t.tname = "张三" ORDER BY sc.score DESC LIMIT 1; # 法二 -- 1.先查询[张三]老师所带的课程编号cid和tid -- SELECT * FROM teacher t LEFT JOIN course c ON t.tid = c.tid WHERE t.tname = "张三"; -- 2.将以上结果与成绩表sc关联 -- SELECT sc.sid,a.cid,a.cname,a.tname,sc.score FROM (SELECT t.tid,t.tname,c.cid,c.cname FROM teacher t LEFT JOIN course c ON t.tid = c.tid WHERE t.tname = "张三") a LEFT JOIN sc ON a.cid = sc.cid ORDER BY sc.score DESC LIMIT 1; -- 3.将以上结果与学生表student关联 -- SELECT s.sid 学号,s.sname 学生姓名,a.cname 课程,a.tname 教师姓名,a.score 成绩 FROM (SELECT sc.sid,a.cid,a.cname,a.tname,sc.score FROM (SELECT t.tid,t.tname,c.cid,c.cname FROM teacher t LEFT JOIN course c ON t.tid = c.tid WHERE t.tname = "张三") a LEFT JOIN sc ON a.cid = sc.cid ORDER BY sc.score DESC LIMIT 1) a LEFT JOIN student s ON a.sid = s.sid;
34 变量的使用
1
假设成绩有重复,查询选修[张三]老师所授课程的学生中,成绩最高的学生信息及成绩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
SET @score:=NULL,@rank:=0;
SELECT * FROM (SELECT a.*, CASE WHEN @score=score THEN @rank ELSE @score:=score AND @rank:=@rank+1 END rk FROM (SELECT s.sid,s.sname,sc.score,c.cid,c.cname FROM teacher t LEFT JOIN course c ON t.tid = c.tid LEFT JOIN sc ON c.cid = sc.cid LEFT JOIN student s ON s.sid = sc.sid WHERE t.tname = "张三") a) s ORDER BY rk DESC LIMIT 1;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
SELECT * FROM (SELECT a.*, CASE WHEN @score=score THEN @rank ELSE @score:=score AND @rank:=@rank+1 END rk FROM (SELECT s.sid,s.sname,sc.score,c.cid,c.cname FROM teacher t LEFT JOIN course c ON t.tid = c.tid LEFT JOIN sc ON c.cid = sc.cid LEFT JOIN student s ON s.sid = sc.sid WHERE t.tname = "张三") a,(SELECT @score:=NULL,@rank:=0) t) s ORDER BY rk DESC LIMIT 1;
41 current_day(),substring(),year(),now()
1 2 3
current_day() 2024-10-14
now() 2024-10-14 11:01:11
1 2 3 4 5 6 7 8 9 10
按照出生日期来算,当前月日 < 出生年月的月日 则年龄减一
SELECT student.SId,CASE WHEN SUBSTRING(CURRENT_DATE(),6,10)-SUBSTRING(Sage,6,10)>=0 THEN YEAR(CURRENT_DATE())-YEAR(Sage) ELSE YEAR(CURRENT_DATE())-YEAR(Sage)-1 END age FROM student
1 2 3 4 5 6 7
SELECT Sno, Sname, YEAR(CURDATE()) - YEAR(Sage) - (DATE_FORMAT(CURDATE(), '%m%d') < DATE_FORMAT(Sage, '%m%d')) AS Age FROM student;
42 week
1 2 3 4 5 6 7 8
查询本周过生日的学生
-- 【分析】使用week()函数 SELECT *, WEEK(sage), WEEK(NOW()) FROM student WHERE WEEK(sage)=WEEK(NOW());
43 month
1 2 3 4 5 6 7 8 9
查询本月过生日的学生
-- 【分析】使用month()函数 -- SELECT *, MONTH(sage), MONTH(NOW()) FROM student WHERE MONTH(sage)=MONTH(NOW());
44 month
1 2 3 4 5 6 7
查询下月过生日的学生
SELECT *, MONTH(sage), MONTH(NOW()) FROM student WHERE MONTH(sage)=MONTH(NOW())+1;
SELECT * from ( SELECT Sno from sc where Cno and Sno='01' in ( SELECT Cno from sc where Sno='01') group by Sno ) t1 left join ( SELECT Sno from sc where Cno not in ( SELECT Cno from sc where Sno='01') group by Sno ) t2 on t1.Sno=t2.Sno where t2.Sno is null
-- 1.先查询出选修了张三老师讲授课程的sid -- SELECT s.sid FROM teacher t LEFT JOIN course c ON t.tid = c.tid LEFT JOIN sc ON c.cid = sc.cid LEFT JOIN student s ON sc.sid = s.sid WHERE tname = "张三"; -- 2.与学生表student关联,筛选出不在以上结果内的sid -- SELECT s.* FROM student s WHERE sid NOT IN (SELECT s.sid FROM teacher t LEFT JOIN course c ON t.tid = c.tid LEFT JOIN sc ON c.cid = sc.cid LEFT JOIN student s ON sc.sid = s.sid WHERE tname = "张三");
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
select sid from student where sid not in ( select sid from sc where cid in ( select cid from teacher t inner join course c on t.tid=c.tid ) group by sid )
11
1 2 3 4 5 6 7
select a.sid,b.sname,avg(a.score) as avg_score from sc a left join student b on a.sid = b.sid where a.score < 60 group by a.sid having count(a.cid) >= 2;
13
14
14 case when round 值得注意
1 2 3 4 5 6 7 8 9 10 11 12 13
SELECT MIN(score) min_score ,MAX(score) max_score ,AVG(score) avg_score ,COUNT(1) stu_number ,SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END)/COUNT(1) 及格率 ,SUM(CASE WHEN score >= 70 AND score < 80 THEN 1 ELSE 0 END)/COUNT(1) 中等率 ,SUM(CASE WHEN score >= 80 AND score < 90 THEN 1 ELSE 0 END)/COUNT(1) 优良率 ,SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END)/COUNT(1) 优秀率 FROM sc LEFT JOIN course c ON sc.cid = c.cid GROUP BY sc.cid ORDER BY stu_number DESC ,sc.cid ASC;
1 2 3 4 5 6
SELECT courseid,MAX(score) AS '最高分', MIN(score)AS '最低分' ,AVG(score) AS '平均分' ,COUNT(*) AS '选修人数', SUM(CASE WHEN student_score.score >= 60 THEN 1 ELSE 0 END)/COUNT(*) AS '及格率', SUM(CASE WHEN student_score.score >= 70 AND student_score.score< 80 THEN 1 ELSE 0 END)/COUNT(*) AS '中等率', SUM(CASE WHEN student_score.score >= 80 AND student_score.score<90 THEN 1 ELSE 0 END)/COUNT(*) AS '优良率', SUM(CASE WHEN student_score.score >= 90 THEN 1 ELSE 0 END)/COUNT(*) AS '优秀率' FROM student_score GROUP BY courseid ORDER BY COUNT(*)DESC,student_score.courseid ASC ;
15 PARTITION BY 下面那个with案例值得注意
1 2 3 4 5 6 7 8 9 10 11
SELECT Sno, Cno, score, DENSE_RANK() OVER (PARTITION BY Cno ORDER BY score DESC) AS ranking FROM sc ORDER BY Cno, score DESC; 在上述查询中,ORDER BY Cno, score DESC是最终的排序,它确保结果首先按课程号排序,然后按分数降序排序。如果你只关心排名而不关心最终排序顺序,可以省略此ORDER BY子句。
1 2 3 4 5 6 7 8 9 10
案例
select Department, Employee, Salary from ( select d.name Department, ee.name Employee, ee.salary Salary, dense_rank() over(partition by departmentId order by salary desc) ranks from Employee ee left join Department d on ee.departmentId = d.id ) t where ranks <= 3
1 2 3 4 5 6 7 8 9 10 11 12 13
案例
WITH t AS ( SELECT employee_id, department_id, primary_flag, COUNT(*) OVER(PARTITION BY employee_id) AS count_over FROM Employee ) SELECT employee_id,department_id FROM t WHERE count_over = 1 or primary_flag = 'Y'
16 变量的使用 法一没看懂 法二法六 值得注意
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
!16 法一 -- 1、学生的总成绩 -- SELECT sid,SUM(score) sum_score FROM sc GROUP BY sid ORDER BY sum_score DESC;
-- 2、名次排序 -- SELECT a.*, @rank:=IF(@sco=sum_score,' ',@rank+1) rk FROM (SELECT sid, SUM(score) sum_score FROM sc GROUP BY sid ORDER BY sum_score DESC) a,(select @sco:=null,@rank:=0) b
1 2 3 4 5 6
法二 (法二-法五是leecode的例子,但用了这里的数据,把sc行数据理解成是总成绩) select a.Sno, a.score,(select count(b.score)+1 --结果有莫名错误 from sc as b where b.score>a.score) as 'r' from sc as a order by 'r';
1 2 3 4 5 6 7
select a.Sno, a.score,(select count(b.score)+1 --这样接正确了,奇怪 from sc as b where b.score>a.score) as r from sc as a order by r;
--等同于rank窗口函数实现的结果
1 2 3 4
法三 (法二-法五是leecode的例子,但用了这里的数据,把sc行数据理解成是总成绩)
select sc.Sno, sc.score,DENSE_RANK() OVER(ORDER BY sc.score desc) as r from sc;
1 2 3 4
法四 (法二-法五是leecode的例子,但用了这里的数据,把sc行数据理解成是总成绩)
select sc.Sno, sc.score,RANK() OVER(ORDER BY sc.score desc) as r from sc;
1 2 3 4
法五 (法二-法五是leecode的例子,但用了这里的数据,把sc行数据理解成是总成绩)
select sc.Sno, sc.score,ROW_NUMBER() OVER(ORDER BY sc.score desc) as r from sc;
1 2 3 4 5 6 7 8
法六 (法二-法五是leecode的例子,但用了这里的数据,把sc行数据理解成是总成绩)
select a.id, a.score, count(*) as r from scores a left join scores b on a.score < b.score group by id, score order by score DESC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
错误写法 (法二-法五是leecode的例子,但用了这里的数据,把sc行数据理解成是总成绩)
select * from sc as a where EXISTS ( select b.score from sc as b where a.Sno!=b.Sno and a.score<=b.score );
select a.Sno, count(*) as coun from SC as a where a.score<=( select b.score from SC as b where a.Sno!=b.Sno ) group by a.Sno order by coun;
1 2 3 4 5 6 7 8 9 10 11 12 13
SELECT s.Sno, s.Sname, SUM(sc.score) AS TotalScore, DENSE_RANK() OVER (ORDER BY SUM(sc.score) DESC) AS Rank FROM student s JOIN SC sc ON s.Sno = sc.Sno GROUP BY s.Sno, s.Sname ORDER BY TotalScore DESC;
!17 不会 SELECT sc.cid 课程编号,c.cname 课程名称,COUNT(1) 选修人数 ,CONCAT(ROUND(SUM(CASE WHEN sc.score >=0 AND sc.score <= 60 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(0-60]' ,CONCAT(ROUND(SUM(CASE WHEN sc.score >=60 AND sc.score <= 70 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(60-70]' ,CONCAT(ROUND(SUM(CASE WHEN sc.score >= 70 AND sc.score <= 85 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(70-85]' ,CONCAT(ROUND(SUM(CASE WHEN sc.score >= 85 AND sc.score <= 100 THEN 1 ELSE 0 END)/COUNT(1),2),'%') AS '(85-100]' FROM sc LEFT JOIN course c ON sc.cid = c.cid GROUP BY sc.cid; -- concat的作用是将两个字符拼接起来 --
!18 不会 好像有点问题 SELECT a.*,c.cname FROM sc a LEFT JOIN course c ON a.cid = c.cid WHERE (SELECT COUNT(1) FROM sc b WHERE b.cid = a.cid AND b.score > a.score) < 3 ORDER BY cid DESC,score DESC;
19 SELECT sc.sid 学生编号,s.sname 学生姓名,COUNT(sc.cid) 选课数量 FROM sc LEFT JOIN student s ON sc.sid = s.sid GROUP BY sc.sid,s.sname HAVING COUNT(sc.cid) = 2;
20 SELECT sc.sid 学生编号,s.sname 学生姓名,COUNT(sc.cid) 选课数量 FROM sc LEFT JOIN student s ON sc.sid = s.sid GROUP BY sc.sid,s.sname HAVING COUNT(sc.cid) = 2;
21 x
!22 SELECT * FROM student WHERE sname LIKE '%风%';
23 SELECT sname 姓名,ssex 性别,COUNT(*) 同名人数 FROM student GROUP BY sname,ssex;
24 x+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
25 ! select a.Cno,b.Cname,avg(a.score) as avg_score -- 这里有b.Cname错误了 from SC a left join Course b on a.Cno = b.Cno group by a.Cno order by avg_score desc,a.Cno asc;
26 select a.sid,b.sname,avg(a.score) as avg_score from sc a left join student b on a.sid = b.sid group by a.sid having avg_score >= 85;
33 # 法一 SELECT * FROM teacher t LEFT JOIN course c ON t.tid = c.tid LEFT JOIN sc ON c.cid = sc.cid LEFT JOIN student s ON s.sid = sc.sid WHERE t.tname = "张三" ORDER BY sc.score DESC LIMIT 1; # 法二 -- 1.先查询[张三]老师所带的课程编号cid和tid -- SELECT * FROM teacher t LEFT JOIN course c ON t.tid = c.tid WHERE t.tname = "张三"; -- 2.将以上结果与成绩表sc关联 -- SELECT sc.sid,a.cid,a.cname,a.tname,sc.score FROM (SELECT t.tid,t.tname,c.cid,c.cname FROM teacher t LEFT JOIN course c ON t.tid = c.tid WHERE t.tname = "张三") a LEFT JOIN sc ON a.cid = sc.cid ORDER BY sc.score DESC LIMIT 1; -- 3.将以上结果与学生表student关联 -- SELECT s.sid 学号,s.sname 学生姓名,a.cname 课程,a.tname 教师姓名,a.score 成绩 FROM (SELECT sc.sid,a.cid,a.cname,a.tname,sc.score FROM (SELECT t.tid,t.tname,c.cid,c.cname FROM teacher t LEFT JOIN course c ON t.tid = c.tid WHERE t.tname = "张三") a LEFT JOIN sc ON a.cid = sc.cid ORDER BY sc.score DESC LIMIT 1) a LEFT JOIN student s ON a.sid = s.sid;
34 ! rank dense_rank也行 SELECT * FROM (SELECT a.*, CASE WHEN @score=score THEN @rank WHEN @score:=score THEN @rank:=@rank+1 END rk FROM (SELECT s.sid,s.sname,sc.score,c.cid,c.cname FROM teacher t LEFT JOIN course c ON t.tid = c.tid LEFT JOIN sc ON c.cid = sc.cid LEFT JOIN student s ON s.sid = sc.sid WHERE t.tname = "张三") a,(SELECT @score:=NULL,@rank:=0) t) s WHERE rk=1;
35 SELECT a.sid,a.cid,a.score FROM sc a INNER JOIN sc b ON a.sid = b.sid WHERE a.cid != b.cid AND a.score = b.score GROUP BY a.cid,a.sid;
36 ! SELECT sid,cid,score,rk FROM( SELECT sc.*, @rank:=if(@c_cid=cid,if(@sco=score,@rank,@rank+1),1) rk, @sco:=score, @c_cid:=cid FROM sc,(SELECT @sco=null,@rank:=0,@c_cid:=null) b ORDER BY cid,score DESC) a where a.rk<3;
37 # 法一 SELECT cid,COUNT(sid) 选修人数 FROM sc GROUP BY cid HAVING COUNT(sid) > 5; # 法二 SELECT cid,COUNT(1) 选修人数 FROM sc GROUP BY cid HAVING COUNT(1) > 5; -- 知识点补充 -- # COUNT(1) COUNT(*) COUNT(列名)的区别 # COUNT(1)包含忽略所有列,用1代表代码行,统计时不会忽略列值为NULL # COUNT(*)包含所有列,相当于行数,统计时,不会忽略列值为NULL # COUNT(列名)只包含列名那一列,统计时忽略列为NULL(某字段为NULL,不计数)
38 x
39 SELECT s.* FROM sc INNER JOIN student s ON sc.sid = s.sid GROUP BY sid HAVING COUNT(1) = (SELECT COUNT(1) FROM course); SELECT s.* FROM sc INNER JOIN student s ON sc.sid = s.sid GROUP BY sid HAVING COUNT(sc.cid) = (SELECT COUNT(cid) FROM course);
40 -- 【分析】使用日期函数进行相减 -- SELECT *,YEAR(CURDATE())-YEAR(sage) 年龄 FROM student; SELECT *,YEAR(NOW())-YEAR(sage) 年龄 FROM student;
41 ! -- 【分析】日期相减函数timestampdiff(year\,参数1,参数2) -- SELECT *, TIMESTAMPDIFF(YEAR,sage,NOW()) age FROM student;
1 2 3 4 5 6 7
SELECT Sno, Sname, YEAR(CURDATE()) - YEAR(Sage) - (DATE_FORMAT(CURDATE(), '%m%d') < DATE_FORMAT(Sage, '%m%d')) AS Age FROM student;
1 2 3 4 5 6 7 8 9 10
SELECT Sno, Sname, Sage, CASE WHEN DATE_FORMAT(CURDATE(), '%m%d') < DATE_FORMAT(Sage, '%m%d') THEN YEAR(CURDATE()) - YEAR(Sage) - 1 ELSE YEAR(CURDATE()) - YEAR(Sage) END as actual_age FROM student;
42
1 2 3 4 5 6 7
42 -- 【分析】使用week()函数 SELECT *, WEEK(sage), WEEK(NOW()) FROM student WHERE WEEK(sage)=WEEK(NOW());
43
1 2 3 4 5 6
43 SELECT *, WEEK(sage), WEEK(NOW()) FROM student WHERE WEEK(sage)=WEEK(NOW())+1;
44
1 2 3 4 5 6 7
44 -- 【分析】使用month()函数 -- SELECT *, MONTH(sage), MONTH(NOW()) FROM student WHERE MONTH(sage)=MONTH(NOW());
45
1 2 3 4 5 6
45 SELECT *, MONTH(sage), MONTH(NOW()) FROM student WHERE MONTH(sage)=MONTH(NOW())+1;