云数据库技术

SQL编程大师李鹏军:凭借高效的SQL策略,让算法设计与代码性能完美融合

Image

数据库编程大赛:只用一条 SQL 秒杀 100 万张火车票

2024 第二届数据库编程大赛于 12 月 5 日正式开启初赛!由 NineData 和云数据库技术社区主办,华为云、Doris等协办单位和媒体共同举办。比赛要求选手设计一套SQL算法,只用一条 SQL 秒杀 100 万张火车票,让乘客都都能顺利坐上火车回家过年。查看赛题详情

以下是本次决赛第8名,SQL编程大师李鹏军的参赛介绍:

Image
参赛选手:李鹏军
个人简介:就职于QuestMobile公司,从事数据开发工作9年。
参赛数据库:SQL Server
性能评测:百万级数据代码性能评测 5.230 秒
综合得分:71

以下是李鹏军选手的算法说明,结尾附完整SQL:

一、车次分配

    思路和普通挑战的思路相同。

二、车厢分配。

    总体思路:乘客编号减去车次的起始乘客编号,除以车厢座位数100,向上取整。

三、座位分配

    1)排数。

    总体思路:乘客编号最后两位,除以每排座位数5,向上取整。

    细节:

        特殊值,乘客编号为100的整数倍时,结果是0,而不是期待的20排。通过转换的小技巧处理一下。

    2)列数(具体的座位( A,B,C,E,F ))。

    总体思路:乘客编号减一,除以5得到的余数再+1。

    细节:

        特殊值,乘客编号为5的整数倍时,结果是0,而不是期待的5排。通过转换的小技巧处理一下。

参赛完整SQL:
select t.passenger_id,t.departure_station,t.arrival_station    ,t.train_id    ,case when t.ticket_status = 1 then CONCAT(t.coach_number,'') else null end coach_number    ,case when t.ticket_status = 1 then t.seat_number when t.ticket_status = 2 then '无座' else null end seat_numberfrom (    select t.passenger_id,t.departure_station,t.arrival_station,t2.train_id        ,case when t.person_Rid between seat_count_all_step_lag + 1 and seat_count_all_step then 1  --有座            when t.person_Rid between seat_count_all + seat_count_all_step_lag/10 + 1 and seat_count_all + seat_count_all_step/10 then 2    --无座            else 3  --无票         end ticket_status        ,CEILING((person_Rid-seat_count_all_step_lag)*1.0/100) coach_number  --车厢号        ,CEILING(((person_Rid-1)%100+1)*1.0/5) row_num   --第几排        ,(person_Rid-1)%5+1 col_num   --第几列(具体的座位( A,B,C,E,F ))        ,concat(CEILING(((person_Rid-1)%100+1)*1.0/5),case (person_Rid-1)%5+1 when 1 then 'A' when 2 then 'B' when 3 then 'C' when 4 then 'E' when 5 then 'F' end) seat_number     --行列组合的最终座位号    from (        select passenger_id,departure_station,arrival_station            ,ROW_NUMBER() over(partition by departure_station,arrival_station order by passenger_id) person_Rid --相同起点终点的所有乘客进行编号        from passenger    ) t    left join (        select train_id,departure_station,arrival_station,seat_count            ,seat_count_all_step            ,coalesce(lag(seat_count_all_step) over(partition by departure_station,arrival_station order by train_id),0) seat_count_all_step_lag    --相同起点终点的列车,上一车次允许乘坐乘客的结束编号            ,seat_count_all        from (            select train_id,departure_station,arrival_station,seat_count                ,sum(seat_count) over(partition by departure_station,arrival_station order by train_id) seat_count_all_step --相同起点终点的列车从第一车次到当前车次的总座位数,也是当前车次允许乘坐乘客的结束编号                ,sum(seat_count) over(partition by departure_station,arrival_station) seat_count_all --相同起点终点的所有列总的座位数总和            from train        ) t    ) t2 on t.departure_station = t2.departure_station and t.arrival_station = t2.arrival_station and ( t.person_Rid between seat_count_all_step_lag + 1 and seat_count_all_step/*有坐票*/ or t.person_Rid between seat_count_all + seat_count_all_step_lag/10 + 1 and seat_count_all + seat_count_all_step/10/*百分之10的无座票*/ )) torder by t.passenger_id;

《数据库编程大赛》

下一次再聚!

感谢大家对本次《数据库编程大赛》的关注和支持,欢迎加入技术交流群,更多精彩活动不断,我们下次再相聚!

Image