12月27日,NineData和云数据库技术社区主办,华为云、火山引擎、开源中国、云和恩墨、TDengine、云猿生数据、DORIS、ITPUB等协办单位和媒体,共同举办了本次《数据库编程大赛》。大赛题目「用一条SQL给出扑克牌24点的计算表达式」,截至比赛当天,本次大赛共收集了近200份SQL代码参赛报名。
有一张表 cards,id 是自增字段的数字主键,另外有4个字段 c1,c2,c3,c4 ,每个字段随机从 1~10 之间选择一个整数,要求选手使用一条 SQL 给出 24 点的计算公式,返回的内容示例如下图:
其中 result 字段是计算的表达式,只需返回1个解,如果没有解,result 返回null。具体比赛玩法参考:数据库编程大赛:一条SQL计算扑克牌24点
本次大赛的评委,均是数据库领域的领军人物,通过主办方NineData的邀请,组成2023年《数据库编程大赛》强大的评审嘉宾团。
《数据库编程大赛》评审嘉宾团
本次大赛主要会从以下4个方面评审,一定要注意下面的评审规则!
正确性
由组委会验证,只有结果正确才会进入评委评选流程。
性能
总得分占比 50% ,由组委会给出测试成绩(第一名 50 分,第二名 45 分,第三名 42 分,第四名 40 分,第 5 名 39 分,后面每排名下降一名减少1分,以此类推,最低得 20 分)
代码创新性
总得分占比 30% ,由评委打分( 0~30 分)
代码易读性
总得分占比 20%?,由评委打分( 0~20 分)
经过大赛组委会对参赛200份SQL代码的初步验证和确认,确保其正确性。在接下来的百万级别性能评测中,我们选出了最强的8位选手,成功晋级到决赛答辩环节。
本次大赛由8位权威评委组成的专家团队对选手的SQL参赛代码和答辩解读进行评分。评委们将着重考察代码的创新性和易读性,并将分别对这两个方面进行打分。最终,大赛组委会将根据综合得分,确定选手的最终排名。
以下是本次数据库编程大赛的最终排名:
参赛选手:李家的张麻子
个人简介:ETL工程师
参赛数据库:SQL Server
性能评测:百万级数据代码性能评测 5.52秒
综合得分:72.6
以下是李家的张麻子选手的代码说明思路:
选手采用的是“人工”穷举算法。值得一提的是,该选手是少数成功使用ChatGPT生成SQL的。首先通过详细列举和排序的方式,全面呈现了所有可能性,并在此基础上由ChatGPT生成SQL代码,再进行适当调整。尽管这种方法稍显粗暴,但是打破常规,正确的运用AI,也是一种新颖的方式。?
参赛选手:李立涵
个人简介:南京航空航天大学的研究生
参赛数据库:MySQL
性能评测:百万级数据代码性能评测 超过1分钟
综合得分:75
以下是李立涵选手的代码说明思路简介:
1.运算表达式的简化
2.测试集中四个数字的全排列
3.计算24点的方式
4.对算式结果进行聚合
参赛选手:傅昌林
个人简介:HBI Solutions, Inc, VP Engineering
参赛数据库:SQL Server
性能评测:百万级数据代码性能评测 11.45秒
综合得分:78.8
以下是傅昌林选手的代码说明思路简介:
1. 数据范围估计
2. 由于只有715种数字组合且每种组合至多需要一种解答, 算法的主要思想是构建出这个结果集, 对于每条查询数据在这个结果集里寻找匹配
3. 随后按照具体的12条步骤生成最终结果。
参赛选手:张泽鹏
个人简介:杭州隐函科技有限公司联创,技术负责人
参赛数据库:PostgreSQL
性能评测:百万级数据代码性能评测 2.46秒
综合得分:82.2
以下是张泽鹏选手的代码说明思路简介:
本算法用了取巧的方法:提前计算好4个1~10数值求24的结果,执行查询时,直接通过特征向量来查询;思路类似于“相似图片搜索”,先提前计算好图片库中每张图片的特征向量,后续通过特征向量做相似搜索即可。
算法原理如下:
1. 预计算:因为`result`中数值的顺序无关,因此先对`10 ^ 4 = 10000`个数组做无序去重,获得715个顺序无关的数组;经过计算可得715中只有566个组合能计算出`24`。
2. 将这566个公式预置在SQL文件中,即代码中的`expressions(result)`。
3. 提取公式的特征向量
4. 得知最终测试数据集内会包含重复的题目(即c1、c2、c3、c4)会有相同,这些相同的题目只计算一次。即代码中`rounds(ids, c1, c2, c3, c4)`。
5. 用相同的方法,计算`rounds`中每道题目的特征向量,即代码中的`rounds_features(ids, features)`。
6. 然后根据特征向量,`rounds_features`从`results`中匹配出结果,并展开得到每道题目的结果`cards_results(id, result)`。
7. 最后与原始表`left join`获得最终结果。
参赛选手:郭其
选手简介:中国移动设计院? ?数据库技术专家负责人??
参赛数据库:Oracle
性能评测:百万级数据代码性能评测?1.1秒
综合得分:84.6
以下是郭其选手的代码说明思路简介:
一、根据小括弧的优先级,给出预设的计算形态
二、提炼其中的公共形态用临时表给予归类
三、减枝+反推,减少运算量
参赛选手:卢涛
选手简介:ITPUB Oracle开发版版主
参赛数据库:MySQL
性能评测:百万级数据代码性能评测?0.89秒
综合得分:85.8
以下是卢涛选手的代码说明思路简介:
1. 采取查表法,预先用其他方法((grubbyoo 编写的SQL ,552条6秒) (C语言566条0.3秒))生成4个数四则运算能算出24点的组合,包括点数从小到大排序拼接成字符串和输出结果,把它保存在SQL的CTE表中备查。
2. 为了解决采用拼接union select或values()的长度超过10K字节限制的问题,主要采取了压缩空间的技巧。
3. 解决测试数据和已知结论对应关系。cards表包含数字1到10的全排列,共10000种。
4. 接下来的优化点主要在于建立更高效的关联字段。
参赛选手:柳胜勋
个人简介:PingCAP/TiDB研发工程师
参赛数据库:MySQL
性能评测:百万级数据代码性能评测 0.88秒
综合得分:87.2
以下是柳胜勋选手的代码说明思路简介:
1. 生成存在的组合的答案集,转成json,并压缩,因为不压缩SQL过长。
2. 在SQL中,解压答案并转换成临时表,然后使用GROUP BY处理,强制走HASH JOIN。
3. 使用LEFT JOIN算出结果。
参赛选手:郑凌云
个人简介:淘宝,负责推荐系统开发
参赛数据库:MySQL
性能评测:百万级数据代码性能评测 0.67秒
综合得分:95
以下是郑凌云选手的代码说明思路简介:
0. 核心:因为4张牌计算24点时的顺序可任意互换,所以不同排列的4张牌可视为同一组合。采用质数编码,把1到10映射成2到29内的质数,4张牌的积可作为该组合的唯一编码
1. 本地写代码,通过简单的回溯算法,生成24点游戏的所有解:152,((1+1)+1)*8,156,(6*2)*(1+1),...
2. 受限于代码大小10k限制,通过把上一步生成的数据进行压缩:SELECT REPLACE(TO_BASE64(COMPRESS('152,((1+1)+1)*8,156,(6*2)*(1+1),...')), '\n', '')
3. 提交的代码中,先对上一步生成的数据解压缩:UNCOMPRESS(FROM_BASE64('XXXX')),并通过递归CTE生成查询表:152,((1+1)+1)*8;156,(6*2)*(1+1);...
4. 对输入表LEFT JOIN上一步生成的查询表,关联的键值是对c1,c2,c3,c4做质数编码后的积。
本次《数据库编程大赛》前30名通过正确性验证的选手,也是会获得一份精美礼品,感谢大家对本次大赛的关注和支持,我们下次再相聚!