只需掌握四个查询,就能解决 95% 的 SQL 问题

在数据分析和管理中,掌握复杂查询逻辑是关键技能。即使在人工智能应用中,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 的同学选修的所有课程,并且在相同学期内选修这些课程的学生。

查询中的逻辑解读

韦恩图:学生 s s s 选修的课程 与 928521 选修的课程 的关系。 U U U 表示所有学生:
image.png

Q1: s s s 的课程要与 928521 的课程有交集。

Q2: 928521 的课程是 s s s 的课程的子集,928521 的任何课程都被 s s s 选修了。

Q3: s s s 的课程是928521 的课程的子集,928521 的任何没有选修的课程, s s s 不可能选修。

Q4: s s s 的课程和 928521 的课程是同一个集合。

解决问题步骤

1.将自然语言查询翻译成一阶逻辑 (First Order Language) 语言表达 (一阶逻辑表达式不包含 全称量词逻辑蕴含);

2.将一阶逻辑语言翻译成关系代数 (Relational Algebra) 语言表达;

3.将关系代数语言翻译成 SQL 查询。

Step1. 自然语言 --> 一阶逻辑

这里我先规定一些变量和谓词:

  • 变量: s s s 来表示某个学生, c c c 表示某个课程, q q q 表示某个学期。
  • 谓词: e n r o l l ( s , c , q ) enroll(s,c,q) enroll(s,c,q) 表达某个学生 s s s 在某个学期 q q q 选修了课程 c c c。为了表达式的简单,我们不单独为学生和课程定义谓词了。

Q1:描述一个学生集合,这些学生要选修 928521 这个同学选修了的课程,并且还是在同一学期选修的:
{ s ∣ ( ∃ c ) ( ∃ q ) [ e n r o l l ( 928251 , c , q ) ∧ e n r o l l ( s , c , q ) ] ∧ s ≠ 928251 } \{s|(\exists c)(\exists q)[enroll(928251,c,q)\land enroll(s,c,q)]\land s\not=928251\} { s(c)(q)[enroll(928251,c,q)enroll(s,c,q)]s=928251}

Q2:根据 s s s 选修了 928521 的所有课程,如果 928521 选修了某门课, s s s 必定也选修了 (因为 s s s 上了 928521 所有的课):
{ s ∣ ( ∀ c ) ( ∀ q ) [ e n r o l l ( 928251 , c , q ) ⇒ e n r o l l ( s , c , q ) ] ∧ s ≠ 928251 } \{s|(\forall c)(\forall q)[enroll(928251,c,q)\Rightarrow enroll(s,c,q)]\land s\not=928251\} { s(c)(q)[enroll(928251,c,q)enroll(s,c,q)]s=928251}
Q3:根据 s s s 选修 928521 的课,如果 s s s 选修了某门课,928521 必定也选修了:
{ s ∣ ( ∀ c ) ( ∀ q ) [ e n r o l l ( s , c , q ) ⇒ e n r o l l ( 928251 , c , q ) ] ∧ s ≠ 928251 } \{s|(\forall c)(\forall q)[enroll(s,c,q)\Rightarrow enroll(928251,c,q)]\land s\not=928251\} { s(c)(q)[enroll(s,c,q)enroll(928251,c,q)]s=928251}
Q4:Q2 和 Q3 条件的并:
{ s ∣ ( ∀ c ) ( ∀ q ) [ e n r o l l ( s , c , q ) ⇔ e n r o l l ( 928251 , c , q ) ] ∧ s ≠ 928251 } \{s|(\forall c)(\forall q)[enroll(s,c,q)\Leftrightarrow enroll(928251,c,q)]\land s\not=928251\} { s(c)(q)[enroll(s,c,q)enroll(928251,c,q)]s=928251}
⇔ \Leftrightarrow 表示逻辑等价 (也可以用 ≡ \equiv 表示): q ⇒ p ∧ p ⇒ q ≡ q ⇔ q q\Rightarrow p\land p\Rightarrow q \equiv q\Leftrightarrow q qppqqq

Step2. 一阶逻辑 --> 关系代数

学生表:Student(Sid, Name, Major, Birthdate)
课程表:Course(Cid, CName, Dept)
课程选修表:Enroll(Sid, Cid, Quarter, Grade)

Q1: { s ∣ ( ∃ c ) ( ∃ q ) [ e n r o l l ( 928251 , c , q ) ∧ e n r o l l ( s , c , q ) ] ∧ s ≠ 928251 } \{s|(\exists c)(\exists q)[enroll(928251,c,q)\land enroll(s,c,q)]\land s\not=928251\} { s(c)(q)[enroll(928251,c,q)enroll(s,c,q)]s=928251} 这个一阶逻辑简化了关系代数的每个部分,我们可以把原查询拆分为多个关系代数表达式:

  • T 11 : = π C i d , Q u a r t e r ( σ S i d = 928251 ( E n r o l l ) ) ) T_{11}:=\pi_{Cid,Quarter}(\sigma_{Sid=928251}(Enroll))) T11:=πCid,Quarter(σSid=928251(Enroll))) 对应一阶逻辑表达式 e n r o l l ( 928251 , c , q ) enroll(928251,c,q) enroll(928251,c,q) 。其中 π \pi π 表示选择哪些列, σ \sigma σ 表示关系选择条件。
  • T 12 = π S i d , C i d , Q u a r t e r ( E n r o l l ) T_{12}=\pi_{Sid,Cid,Quarter}(Enroll) T12=πSid,Cid,Quarter(Enroll) 对应一阶逻辑表达式 e n r o l l ( s , c , q ) enroll(s,c,q) enroll(s,c,q)
  • T 13 = σ S i d ≠ 928521 ( T 12 ) T_{13}=\sigma_{Sid\not= 928521}(T_{12}) T13=σ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值