• 3 min read
如何将自然语言完美转换为SQL与关系代数
在学习数据库的过程中,最大的痛点就是:如何把人类常说的“自然语言”需求,准确无误地翻译成“关系代数”甚至是“SQL语句”?
今天,我们将通过一个经典的数据库模型,教大家一个万能的“三步拆解法”。为了让大家能直观地看到查询全貌,我们在进行转换演示前,先放出对应的基础数据表。
1. 基础数据准备:经典的 S-P-J-SPJ 数据库
我们假设有一个供应商、零件、工程项目的管理系统,包含以下四张表:
S 表(供应商表 Supplier)
| SNO (供应商号) | SNAME (供应商名) | STATUS (状态) | CITY (所在城市) |
|---|---|---|---|
| S1 | 精益 | 20 | 天津 |
| S2 | 盛锡 | 10 | 北京 |
| S3 | 东方红 | 30 | 北京 |
P 表(零件表 Part)
| PNO (零件号) | PNAME (零件名) | COLOR (颜色) | WEIGHT (重量) |
|---|---|---|---|
| P1 | 螺母 | 红 | 12 |
| P2 | 螺栓 | 绿 | 17 |
| P3 | 螺丝刀 | 蓝 | 14 |
J 表(工程项目表 Project)
| JNO (工程号) | JNAME (工程名) | CITY (所在城市) |
|---|---|---|
| J1 | 三建 | 北京 |
| J2 | 一汽 | 长春 |
SPJ 表(供应情况表 Supply)
| SNO (供应商号) | PNO (零件号) | JNO (工程号) | QTY (供应数量) |
|---|---|---|---|
| S1 | P1 | J1 | 200 |
| S1 | P2 | J1 | 100 |
| S2 | P1 | J1 | 300 |
2. 核心秘籍:三步拆解法
面对复杂的自然语言描述,不要慌,按照这三步来“解构”句子:
- 找“目标”(对应关系代数的投影 和 SQL 的
SELECT): 看句子最后问的是什么(例如“求…的号码”)。这决定了结果集中需要保留哪些列。 - 找“范围”(对应关系代数的自然连接 和 SQL 的
FROM/JOIN): 根据目标和条件,判断这些信息分散在哪些表里。如果跨越了多个表,就需要将它们通过共同的属性连接起来。 - 找“条件”(对应关系代数的选择 和 SQL 的
WHERE): 寻找句子中的限制性定语(例如“红色的”、“天津的”)。
3. 实战演练
让我们结合上面的具体表数据,来看看这个方法如何应用。
场景一:单表简单条件查询
自然语言:求供应工程 J1 零件的供应商号码 SNO。
- 找目标:供应商号码 SNO /
SELECT SNO - 找范围:已知工程号查供应商号,一张“供应情况表 SPJ”就包含了这俩字段 操作对象为
SPJ表 /FROM SPJ - 找条件:工程为 J1 /
WHERE JNO='J1'
最终转换结果:
- 关系代数:
- SQL语句:
SELECT SNO FROM SPJ WHERE JNO='J1';
(对照数据表:查询 SPJ 表中 JNO 为 J1 的记录,结果将返回 S1, S2)
场景二:多表连接的复杂查询
自然语言:求供应工程 J1 零件为红色的供应商号码 SNO。
- 找目标:供应商号码 SNO /
SELECT SNO - 找范围:涉及工程号(SPJ表)、零件颜色(P表),目标是供应商号(SPJ表)。需要跨表将 SPJ 和 P 连起来 /
FROM SPJ, P - 找条件:工程为 J1 且颜色为红色,同时别忘了隐含的表连接条件(两表的零件号必须相等) /
WHERE JNO='J1' AND SPJ.PNO=P.PNO AND COLOR='红'
最终转换结果:
- 关系代数:
- SQL语句:
SELECT SNO FROM SPJ, P WHERE JNO='J1' AND SPJ.PNO=P.PNO AND COLOR='红';
(对照数据表:P表中红色的零件是P1,再看SPJ表中供应P1给J1的供应商,结果将返回 S1, S2)
场景三:处理特殊逻辑(“没有/不”)
自然语言:求没有使用天津供应商生产的红色零件的工程项目代码 JNO。
- 解题思路:遇到“没有”,通常使用**差运算()**或 SQL 的
NOT IN。先求出“所有”的工程号,再减去“使用了天津供应商红色零件”的工程号。
最终转换结果:
- 关系代数:
- SQL语句:
SELECT JNO FROM SPJ WHERE JNO NOT IN ( SELECT JNO FROM SPJ, P, S WHERE S.CITY='天津' AND COLOR='红' AND S.SNO=SPJ.SNO AND P.PNO=SPJ.PNO );
总结
万变不离其宗。下次遇到再长的自然语言需求,只需拿起笔:画圈标出要查询的最终结果(SELECT),划横线标出涉及的实体名词(FROM),打括号标出限制条件(WHERE)。