# 查询有SQL试卷答题记录的用户的id号、等级和其未完成率(只需关注有答题记录的SQL试卷,使用内连接)
select u.uid, u.level, avg(submit_time is null) incomplete_rate
from examination_info ei
join exam_record er
on ei.exam_id=er.exam_id
join user_info u
on er.uid=u.uid
where ei.tag='SQL'
group by u.uid

# 将用户id按其未完成率排序,并选出前50%的用户号及等级(使用窗口函数+percent_rank()函数)
select uid, level
from (
    select uid, level, percent_rank()over(order by incomplete_rate desc) rank1
    from (
        select u.uid, u.level, avg(submit_time is null) incomplete_rate
        from examination_info ei
        join exam_record er
        on ei.exam_id=er.exam_id
        join user_info u
        on er.uid=u.uid
        where ei.tag='SQL'
        group by u.uid
    ) k1
)k2
where rank1 <=0.5

# (1)筛选出未完成率较高的用户中的6和7级用户
select uid
from(
    select uid, level
    from (
        select uid, level, percent_rank()over(order by incomplete_rate desc) rank1
        from (
            select u.uid, u.level, avg(submit_time is null) incomplete_rate
            from examination_info ei
            join exam_record er
            on ei.exam_id=er.exam_id
            join user_info u
            on er.uid=u.uid
            where ei.tag='SQL'
            group by u.uid
        ) k1
    )k2
    where rank1 <=0.5
) k3
where level=6 or level=7

# 找出(1)中各用户有试卷作答记录的各月里,每个月的答卷数量及完成数量,答题月份标记
select uid, date_format(start_time, '%Y%m') start_month, count(start_time) total_cnt, count(submit_time) complete_cnt, min(start_time) st_tag
from exam_record er
where uid in (
    select uid
    from(
        select uid, level
        from (
            select uid, level, percent_rank()over(order by incomplete_rate desc) rank1
            from (
                select u.uid, u.level, avg(submit_time is null) incomplete_rate
                from examination_info ei
                join exam_record er
                on ei.exam_id=er.exam_id
                join user_info u
                on er.uid=u.uid
                where ei.tag='SQL'
                group by u.uid
            ) k1
        )k2
        where rank1 <=0.5
    ) k3
    where level=6 or level=7
)
group by uid, date_format(start_time, '%Y%m')
# 在找出(1)中各用户有试卷作答记录的各月里,每个月的答卷数量及完成数量,答题月份标记的基础上,为各用户的近期答题月份按从后往前排序编号
select *, rank()over(partition by uid order by st_tag desc) rank_yue
from (
    select uid, date_format(start_time, '%Y%m') start_month, count(start_time) total_cnt, count(submit_time) complete_cnt, min(start_time) st_tag
    from exam_record er
    where uid in (
        select uid
        from(
            select uid, level
            from (
                select uid, level, percent_rank()over(order by incomplete_rate desc) rank1
                from (
                    select u.uid, u.level, avg(submit_time is null) incomplete_rate
                    from examination_info ei
                    join exam_record er
                    on ei.exam_id=er.exam_id
                    join user_info u
                    on er.uid=u.uid
                    where ei.tag='SQL'
                    group by u.uid
                ) k1
            )k2
            where rank1 <=0.5
        ) k3
        where level=6 or level=7
    )
    group by uid, date_format(start_time, '%Y%m')
) k4
# 按月份编号筛选(1)中各用户近三个月的信息,并按题目条件进行排序
select uid, start_month, total_cnt, complete_cnt, rank_yue
from (
    select *, rank()over(partition by uid order by st_tag desc) rank_yue
    from (
        select uid, date_format(start_time, '%Y%m') start_month, count(start_time) total_cnt, count(submit_time) complete_cnt, min(start_time) st_tag
        from exam_record er
        where uid in (
            select uid
            from(
                select uid, level
                from (
                    select uid, level, percent_rank()over(order by incomplete_rate desc) rank1
                    from (
                        select u.uid, u.level, avg(submit_time is null) incomplete_rate
                        from examination_info ei
                        join exam_record er
                        on ei.exam_id=er.exam_id
                        join user_info u
                        on er.uid=u.uid
                        where ei.tag='SQL'
                        group by u.uid
                    ) k1
                )k2
                where rank1 <=0.5
            ) k3
            where level=6 or level=7
        )
        group by uid, date_format(start_time, '%Y%m')
    ) k4
) k5
where rank_yue <= 3
order by uid, rank_yue desc

# 最后按上面查询结果表继续查询,但只查询出题目规定字段
select uid, start_month, total_cnt, complete_cnt
from(
    select uid, start_month, total_cnt, complete_cnt, rank_yue
    from (
        select *, rank()over(partition by uid order by st_tag desc) rank_yue
        from (
            select uid, date_format(start_time, '%Y%m') start_month, count(start_time) total_cnt, count(submit_time) complete_cnt, min(start_time) st_tag
            from exam_record er
            where uid in (
                select uid
                from(
                    select uid, level
                    from (
                        select uid, level, percent_rank()over(order by incomplete_rate desc) rank1
                        from (
                            select u.uid, u.level, avg(submit_time is null) incomplete_rate
                            from examination_info ei
                            join exam_record er
                            on ei.exam_id=er.exam_id
                            join user_info u
                            on er.uid=u.uid
                            where ei.tag='SQL'
                            group by u.uid
                        ) k1
                    )k2
                    where rank1 <=0.5
                ) k3
                where level=6 or level=7
            )
            group by uid, date_format(start_time, '%Y%m')
        ) k4
    ) k5
    where rank_yue <= 3
    order by uid, rank_yue desc
) k6;

以上思路较长,但思路分解较为清晰,主要是每一步都把上一步的子查询嵌进去了,所以显得长

/*完整代码,嵌套多个子循环*/
# 如果没有分步去做,真的写不出来。。
select uid, start_month, total_cnt, complete_cnt
from(
    select uid, start_month, total_cnt, complete_cnt, rank_yue
    from (
        select *, rank()over(partition by uid order by st_tag desc) rank_yue
        from (
            select uid, date_format(start_time, '%Y%m') start_month, count(start_time) total_cnt, count(submit_time) complete_cnt, min(start_time) st_tag
            from exam_record er
            where uid in (
                select uid
                from(
                    select uid, level
                    from (
                        select uid, level, percent_rank()over(order by incomplete_rate desc) rank1
                        from (
                            select u.uid, u.level, avg(submit_time is null) incomplete_rate
                            from examination_info ei
                            join exam_record er
                            on ei.exam_id=er.exam_id
                            join user_info u
                            on er.uid=u.uid
                            where ei.tag='SQL'
                            group by u.uid
                        ) k1
                    )k2
                    where rank1 <=0.5
                ) k3
                where level=6 or level=7
            )
            group by uid, date_format(start_time, '%Y%m')
        ) k4
    ) k5
    where rank_yue <= 3
    order by uid, rank_yue desc
) k6;