2021年了,你还在手写SQL吗?

本文涉及的产品
NLP 自学习平台,3个模型定制额度 1个月
NLP自然语言处理_高级版,每接口累计50万次
NLP自然语言处理_基础版,每接口每天50万次
简介: 2021年了,你还在手写SQL吗?

忆往昔岁月


“你还记得第一份实习,是做什么吗?”

我的第一份算法实习工作,是处理数据。准确地说,是每天手敲30句+SQL,从对话数据库中分析用户高频问题、接通率等信息。


手写SQL是重复性很强的工作,一不小心容易出错,最初的两个月每天为此忙得焦头烂额。


刚刚入门NLP的我天真地想着,“要是模型可以自动生成SQL该多好呀”!

硕士期间,有幸在实验室从事了半年多Text2SQL的科研工作。2021年,我很高兴地看到Text2SQL技术,即通过算法将人的自然语言转换为数据库查询语言SQL,在部分场景中落地应用已经成为了现实。


谈谈自动写SQL的背景


Text2SQL起源于上世纪90年代,是自然语言处理语义解析领域的子任务,核心目标是打破人与结构化数据之间的壁垒,让普通用户可以通过自然语言描述完成复杂数据库的查询工作。


例如我有一张“歌手”相关的表格,歌迷和狗仔队们想知道:

Q:“周杰伦和林俊杰最近的演唱会是什么时候?”

Text2SQL模型自动将问题转换为SQL语言:

A:“SELECT 近期演唱会 FROM singer WHERE 姓名 = 周杰伦 OR 姓名 = 林俊杰”

再返回查询结果:“北京-01.08”和“上海-04.28”



简单的说,以前想从数据库里拿数据或者分析内容,用户要纯手工实现。有了Text2SQL,相当于我雇了一个不花钱不会累的员工(ai模型),只要发布命令(Text),它就会帮我写好SQL。



聊聊技术实现


明白了背景,我们来聊聊技术实现问题。和分类、匹配等很多NLP任务类似,Text2SQL也经历了从早期规则匹配,到现在借助深度学习技术的发展历程,浓缩了一代又一代科学家们的心血。


具体实现方式有很多,为了节省时间,我帮大家抽出了一些代表性的方法。


模版与规则匹配


早期的SQL生成方法主要通过基于统计的模版与规则匹配方式。


SQL查询是一种有很强范式的编程语言,典型特征是可以拆分为“SELECT”和“WHERE”两个片段。再细分一下,几乎90%的SQL语句都可以抽象成如下的模版片段:



AGG表示聚合函数,COLUMN表示需要查询的目标列,WOP表示多个条件之间的关联规则“与/或”,三元组 [COLUMN, OP, VALUE] 构成了查询条件,分别代表条件列、条件操作符、从问题中抽取出的文本片段。*表示目标列和查询条件不止一个!


有了SQL模版,可以先通过统计方法从语料中挖掘出一些高频实体,如人名、地名等,再根据规则填充到模版相应片段即可。来看一个具体 :

Q:价格低于20W的汽车有哪些品牌?

先将问题分词,方便后续处理:“价格 / 低于 / 20W / 的 / 汽车 / 有 / 哪些 / 品牌 ?”

通过预定义规则,很快可以识别 “低于”代表“<”操作符;“低于20W”代表“< 20W”;通过简单数据预处理,还原出条件片段“< 20000”。

通过词性分析和语料统计,识别出“价格”,“20W”,“汽车”是有实际意义的实体。最终通过类似的模版:“$[低于/高于]$的$有哪些?”还原出真实SQL:

A:SELECT 品牌 FROM 汽车 WHERE 价格 < 20000

这里的条件三元组是 [“价格”, “<”, “20000”],目标列为“品牌”,聚合函数为空。


当然通过规则+模版的方式难以穷尽所有自然语言表达,只能处理这种简单的例子。深度学习技术的出现,让盐究员们看到了Text2SQL大放光彩的曙光。


端到端多任务架构


为了充分利用神经网络的特征抽取能力和SQL的语法特点,共享编码器+多任务解码的Seq2Seq架构是一种有效的解决方法。


共享编码器一般是用词向量或预训练语言模型,对query、table和column进行联合编码,捕捉其中隐含的链接关系。其中后两项(表名和列名)统称为数据库模式。例如使用BERT等语言模型时,习惯将输入拼接为 “[CLS] query [SEP] table [SEP] column1 [SEP] column2 [SEP] .... [SEP]”这样的长序列,经过多层Transformer编码,不同table和column对于问题query会有不同权重的相关性。


解码器根据SQL语法特点,设计多个不同的子网络。例如,针对上一小节的SQL模版,可以设计6个子任务分别预测查询目标列、目标列的聚合函数等SQL片段,最终拼接出完整SQL。


多任务架构的优点在于针对不同SQL片段,可以设计有效的损失函数;同时在训练过程中子任务的准确率可以实时监控,便于落地。对此方法感兴趣的读者,可以阅读国防科大的论文M-SQL[1],它在天池NL2SQL[2]中文公开赛上获得了第一名。


端到端抽象语法树解码


这种方法的编码器与前一节类似,但是在解码时将SQL视作一棵抽象语法树,树中各个结点是SQL的关键字(SELECT、WHERE、AND...)或者表名和列名的候选值。生成SQL的过程相当于从树的根结点对语法树做一次深度优先搜索。



以节点“SELECT”为例,“SELECT”节点往下可能包含3个叶子节点:“Column”、“AGG”、“Distinct”,分别代表“选取某一列”、“增加聚合操作”、“对列去重”。从“SELECT”节点向下搜索相当于是3分类任务,根据真实路径和搜索路径依次计算各个节点的交叉熵并求和,作为总损失。


抽象语法树的思想避免了设计各种各样的子网络,对于涉及跨表查询、嵌套查询的复杂数据集有很好的效果。在领域内权威比赛Spider上取得优异成绩的顶会模型IRNet[3]、Rat-SQL[4],都充分借鉴了语法树思想。


其实语法树不仅仅可以生成SQL,还可以生成各种各样好玩的目标序列,例如Python/Java等编程语言,音乐音符等等。CMU的这篇论文[5]从文本生成了Python。


Text2SQL资源大礼包


笔者在Text2SQL领域踩坑半年有余,为避免重复性劳动,我将收集到的资料打包成了一个开源项目,主要包含Text2SQL语义解析数据集、解决方案、参考论文等。欢迎小伙伴们前来


项目地址:https://github.com/yechens/NL2SQL



项目还在持续更新中。对于该领域的部分顶会论文,我加入了自己的解读(BRIDGE:万万没想到,BERT学会写SQL了)。


落地商用的真相


虽然近年该方向在ACL/EMNLP等顶会上出了很多paper,几个知名比赛各家研究院刷的不亦乐乎,不过在我看来Text2SQL实际商用仅处于初级阶段。


究其原因,是准确率还不够高,无法完全满足用户预期。自然语言有很大的熵值,即便同一句话都可以有多种不同理解。同时实际场景中,用户查询内容往往涉及多张表格,查询条件可能非常复杂。语义歧义性、跨表查询、嵌套查询等难点给模型生成准确无误的SQL带来很大挑战



所以当前阶段,大家看到了Text2SQL应用的曙光,但是还未开始大规模推广;更多时候是结合人工干预与纠错,作为对话系统的一个子模块。


回到标题上来,2021年了,你还在手写SQL吗?相信看完本文读者们心里已经有了答案。对于WikiSQL、TableQA等简单的单表数据集,模型已经完全可以cover。但是在现实复杂场景中,还有很长的研究道路要走。


Text2SQL依然是一个很有研究意义的课题,是自然语言处理跨出文本走向多模态的典型代表。相信未来还会有Text2Music、Text2Moive等新技术诞生,更好地服务于人类社会。

相关文章
|
4月前
|
SQL 关系型数据库 MySQL
sql 学习
sql 学习
|
4月前
|
SQL 存储 搜索推荐
SQL游标的原理与在数据库操作中的应用
SQL游标的原理与在数据库操作中的应用
|
6月前
|
SQL Go
YI
|
SQL 存储 关系型数据库
SQL学习总结
SQL学习总结
YI
79 0
|
SQL 存储 JSON
QxOrm使用Sql语句进行数据库操作
之前介绍了纯使用QxOrm的增删改查,接下来介绍使用QxOrm来执行sql语句。这部分也是有必要的。 QxOrm一共提供了1个类2个方法来执行sql语句
420 0
|
SQL 前端开发 Java
sqlserver数据库,mybatis中时间范围查询的应用。
sqlserver数据库,mybatis中时间范围查询的应用。
138 0
一行SQL代码能做什么?(上)
最近在知乎上看到一个问题:一行代码可以做什么?答题者数万计,都是一些非常“高端”的操作,就在想一行SQL代码能做什么呢?
一行SQL代码能做什么?(上)
|
SQL XML 数据库
一行SQL代码能做什么?(下)
最近在知乎上看到一个问题:一行代码可以做什么?答题者数万计,都是一些非常“高端”的操作,就在想一行SQL代码能做什么呢?
一行SQL代码能做什么?(下)
|
SQL XML 数据库
一行SQL代码能做什么?(下)
最近在知乎上看到一个问题:一行代码可以做什么?答题者数万计,都是一些非常“高端”的操作,就在想一行SQL代码能做什么呢? SQL一行代码其实有很多很多,一些常见的比如: SELECT * FROM TableName INSERT INTO TableName VALUES(...) TRUNCATE TABLE TableName ..... 这些就没什么意思了,我们来给大家看一些比较“高级”的。
一行SQL代码能做什么?(下)