[SQL] Window functions and public expressions

1077 Project Staff III

insert image description here

# Write your MySQL query statement below
select project_id, employee_id
from (
    select project_id, e.employee_id, rank() over(partition by project_id order by experience_years desc) as rk
    from Employee e
    join Project p
    on e.employee_id = p.employee_id
) tmp
where tmp.rk = 1;

1285 Find the start and end numbers of consecutive intervals

insert image description here

# Write your MySQL query statement below
select min(log_id) as start_id, max(log_id) as end_id
from (
    select log_id, log_id - rank() over(order by log_id) as num
    from Logs
) t
group by num

train of thought

  1. First rank each number
  2. Subtract your own ranking from these numbers. If the result after subtraction is the same, it means that these numbers are consecutive.
  3. Use the number obtained by subtracting the ranking from logid to perform group by, that is, put all the consecutive numbers in a group, and find the maximum and minimum values ​​of each group.

1596 Most Frequently Ordered Items per Customer

select t.customer_id, t.product_id, p.product_name
from (
    select customer_id, product_id,
    rank() over(partition by customer_id order by count(product_id) desc) as rk
    from Orders
    group by customer_id, product_id
) t
join Products p
on t.product_id = p.product_id
where rk = 1

Summarize

  • There is a pitfall here, the count will not be grouped according to the partition, so the number of counts must be calculated according to the group by group; secondly, the group by is executed before the window function.

1709 Maximum gap between access dates

insert image description here

select user_id, max(datediff(next_visit, visit_date)) as biggest_window
from (
    select  user_id, 
            visit_date, 
            lead(visit_date, 1, "2021-01-01") over(partition by user_id 
            order by visit_date) as next_visit
    from UserVisits
) tmp
group by user_id
order by user_id;

Summarize

  • Pay attention to the parameters of lead(x,y,z) over(), x represents the column to be searched for, y represents the number of positions to go back, and z represents the default value when x+y cannot find a record.

    In this question, lead(visit_date, 1, '2021-01-01') means that what you are looking for is the visit_date column, 1 means visit_date goes back 1 record, and '2021-01-01' means you can't find it when you go back When logging, defaults to '2021-01-01'. The front and back here refer to the front and back after sorting with order by.

1270 Everyone who reports to the CEO of the company

insert image description here

# 写法1
select employee_id from Employees
where manager_id in(
    select employee_id from Employees
    where manager_id in
    (select employee_id from Employees where manager_id=1) 
) and employee_id <> 1;

# 写法2
select distinct e1.employee_id
from Employees e1,Employees e2, Employees e3
where e1.manager_id=e2.employee_id and e2.manager_id=e3.employee_id
and e3.manager_id=1 and e1.employee_id !=1

Summarize

  • Idea 1: Nested queries
  • Idea 2: Combine three tables, this method only employee_id=manager_idtakes effect when the boss is in charge.
  • For idea 2, the question at the beginning was not the four-table query. At first, I thought that employee_id=7this employee could not be queried, but we can find it if we draw the table. The records in Table 3 employee_id=2,manager_id=1can be queried as follows:
 ["employee_id", "employee_name", "manager_id", #表1
 "employee_id", "employee_name", "manager_id", #表2
 "employee_id", "employee_name", "manager_id"] #表3
  [7, "Luis", 4, 
  4, "Daniel", 2, 
  2, "Bob", 1]

1412 Find students whose grades are in the middle

# 写法1
select distinct e.student_id, student_name
from Exam e
left join Student s
on e.student_id = s.student_id
where e.student_id not in (
    select student_id from Exam 
    where (exam_id, score) in ((select exam_id, max(score) from Exam group by exam_id) 
    union all (select exam_id, min(score) from Exam  group by exam_id))
)
order by student_id;

# 写法2
# 根据成绩升序和降序排序,根据学生id分组,去掉成绩排名中为1的记录
select e.student_id, student_name
from (
    select student_id, 
    rank() over(partition by exam_id order by score desc) max_score_rk,
    rank() over(partition by exam_id order by score) min_score_rk
    from Exam
) e
left join Student s
on e.student_id = s.student_id
group by e.student_id
having min(e.max_score_rk) <> 1 and min(e.min_score_rk) <> 1
order by e.student_id;

1767 Search for unexecuted task pairs

with recursive t as 
(
    select task_id, subtasks_count subtask_id from Tasks
    union all
    select task_id, subtask_id-1 from t where subtask_id > 1
)

select t.task_id, t.subtask_id
from t
left join Executed e
on t.task_id = e.task_id and t.subtask_id = e.subtask_id
where e.subtask_id is null;

Summarize

Directly generate all possible (main task id, subtask id) combinations corresponding to each task through recursive, the following is the usage of recursive.

WITH RECURSIVE cte (n) AS
( select 初始值 from table
union all
select 递归内容 from cte where (终止条件)
)

reference

  1. 1285 question ideas
  2. 7 ways to convert rows to columns

Guess you like

Origin blog.csdn.net/weixin_40433003/article/details/130449526