在数据分析和管理中,掌握复杂查询逻辑是关键技能。即使在人工智能应用中,80%以上的时间都用于数据处理。 所谓 “garbage in, garbage out” 说明了数据质量的重要性。 而写好查询是数据处理的第一步。一个错误的查询可能毁掉整个模型。
今天,我将通过一个有趣的案例,向你展示如何从自然语言到SQL查询的转化。这不仅是一次技术之旅,更是一场逻辑的魔法秀。
关系模式 (Relational Schema)
学生表:Student(Sid, Name, Major, Birthdate)
课程表:Course(Cid, CName, Dept)
课程选修表:Enroll(Sid, Cid, Quarter, Grade)
查询的自然语言描述 (Queries)
Q1: 查找那些选修了Sid 为 928521 的同学选修的课程,并且在相同学期内选修这些课程的学生。
Q2: 查找那些选修了Sid 为 928521 的同学选修的所有课程,并且在相同学期内选修这些课程的学生。
Q3: 查找那些仅选修了Sid 为 928521 的同学选修的课程,并且在相同学期内选修这些课程的学生。
Q4: 查找那些仅选修了Sid 为 928521 的同学选修的所有课程,并且在相同学期内选修这些课程的学生。
查询中的逻辑解读
韦恩图:学生 选修的课程 与 928521 选修的课程 的关系。 表示所有学生:
Q1: 的课程要与 928521 的课程有交集。
Q2: 928521 的课程是 的课程的子集,928521 的任何课程都被 选修了。
Q3: 的课程是928521 的课程的子集,928521 的任何没有选修的课程, 不可能选修。
Q4: 的课程和 928521 的课程是同一个集合。
解决问题步骤
1.将自然语言查询翻译成一阶逻辑 (First Order Language) 语言表达 (一阶逻辑表达式不包含 全称量词 和 逻辑蕴含);
2.将一阶逻辑语言翻译成关系代数 (Relational Algebra) 语言表达;
3.将关系代数语言翻译成 SQL 查询。
Step1. 自然语言 –> 一阶逻辑
这里我先规定一些变量和谓词:
-
变量: 来表示某个学生, 表示某个课程, 表示某个学期。 -
谓词: 表达某个学生 在某个学期 选修了课程 。为了表达式的简单,我们不单独为学生和课程定义谓词了。
Q1:描述一个学生集合,这些学生要选修 928521 这个同学选修了的课程,并且还是在同一学期选修的:
Q2:根据 选修了 928521 的所有课程,如果 928521 选修了某门课, 必定也选修了 (因为 上了 928521 所有的课):
Q3:根据 仅 选修 928521 的课,如果 选修了某门课,928521 必定也选修了:
Q4:Q2 和 Q3 条件的并:
表示逻辑等价 (也可以用 表示):
Step2. 一阶逻辑 –> 关系代数
学生表:Student(Sid, Name, Major, Birthdate)
课程表:Course(Cid, CName, Dept)
课程选修表:Enroll(Sid, Cid, Quarter, Grade)
Q1: 这个一阶逻辑简化了关系代数的每个部分,我们可以把原查询拆分为多个关系代数表达式:
-
对应一阶逻辑表达式 。其中 表示选择哪些列, 表示关系选择条件。 -
对应一阶逻辑表达式 。 -
对应一阶逻辑表达式 。 -
对应一阶逻辑表达式 。 -
对应整个 Q1 的一阶逻辑表达式。
Q2: 翻译这个一阶逻辑表达式有些难度,主要在于对全称量词 以及对逻辑蕴含 的转化。因为关系代数没有表达 的表达式,小编已知所有的查询语言都不支持 表达,因为计算它的计算代价很大。在翻译之前我们需要用到:
-
全称量词和存在量词的转化
-
逻辑蕴含的等价
-
摩根定律 (De Morgan’s laws)
变换一阶逻辑表达式:
学生表:Student(Sid, Name, Major, Birthdate)
课程表:Course(Cid, CName, Dept)
课程选修表:Enroll(Sid, Cid, Quarter, Grade)
翻译转化后的一阶逻辑表达式 为关系代数表达式:
-
表示全集 (所有可能的选修信息),其中 表示笛卡尔积。 -
对应一阶逻辑表达式 ,这里需要全集 来表达 negation ()。 -
对应一阶逻辑表达式 ,其中 表示自然连接,等价于逻辑 “与” ()。 -
对应一阶逻辑表达式 。 -
对应一阶逻辑表达式 。 -
对应整个转化后的 Q2 的一阶逻辑表达式。
Q3: ,这里直接给出关系代数表达式:
-
。 -
。 -
。
Q4: 答案为 Q3 与 Q2 的逻辑 “与”: 。
Step3. 关系代数 –> SQL 查询
学生表:Student(Sid, Name, Major, Birthdate)
课程表:Course(Cid, CName, Dept)
课程选修表:Enroll(Sid, Cid, Quarter, Grade)
以 Q2 为例子来写查询 :
CREATE VIEW T21 AS
SELECT Sid, Cid, Quarter
FROM Student, Course;
,其中 :
CREATE VIEW T22 AS
SELECT DISTINCT T21.Sid, T21.Cid, T21.Quarter
EXCEPT
SELECT DISTINCT Sid, Cid, Quarter FROM Enroll;
,其中 :
CREATE VIEW T11 AS
SELECT Cid, Quater
FROM Enroll
WHERE Sid = 928251;
CREATE VIEW T23 AS
SELECT T11.Sid, T11.Cid, T11.Quarter
FROM T11
NATURAL JOIN T22;
:
CREATE VIEW T24 AS
SELECT DISTINCT *
FROM T21
EXCEPT
SELECT DISTINCT *
FROM T23;
上面的 SELECT DISTINCT *
也可以是 SELECT DISTINCT Sid, Cid, Quarter
。
, :
SELECT DISTINCT Sid
FROM T24
WHERE Sid != 928521;
关系代数到 SQL 的对应表总结
这里根据 set semantics (集合语义) 给出的对应表。
原创文章,作者:guozi,如若转载,请注明出处:https://www.sudun.com/ask/88525.html