如何连接多个表并查找对

时间:2016-03-05 14:53:57

标签: sql

我们目前正在学习有关数据库的讲座,我们不确定我们的解决方案是否是解决此类问题的正确方法。

给出以下方案: enter image description here

相关关系的翻译:

  • 讲座( LectureID [PK],LectureTitle, ProfInitials
  • VG( LectureID [PK,FK1], SubjectTitle [PK,FK2]
  • 主题( 标题 [PK],说明)

任务是寻找具有共同主题(“Gebiet”)的讲座(“Vorlesung”)。结果表应包含两个讲座(“VTitel”)的名称和共享主题的标题(“标题”)。

我们提出的解决方案是

SELECT "T1"."VTitel", "T2"."VTitel", "T1"."Titel"
FROM (SELECT v1."VTitel", "Titel" FROM "Vorlesung" v1 NATURAL JOIN "VG" g) AS "T1"
JOIN (SELECT v1."VTitel", "Titel" FROM "Vorlesung" v1 NATURAL JOIN "VG" g) AS "T2"
ON "T1"."Titel" = "T2"."Titel" AND "T1"."VTitel" <> "T2"."VTitel";

这是解决这个问题的正确方法吗?还是有更简单的方法来解决这个问题?

1 个答案:

答案 0 :(得分:1)

看起来它会给你正确的答案,但是在实践中它通常更快(通常,但通常并不总是更具可读性),以避免嵌套的子查询。我假设您已经在关系代数上进行了一些讲座,所以您会注意到,如果您将查询转换为关系形式,则结果相当长(我重命名了您的表和列并使用this site来生成它,但你应该自己动手做; S是Vorlesung,T是VG,b和d是每个表中的两个字段):

π T1.b, T2.b, T1.d ρ T1 ( π v1.b, v1.d ρ v1 S ⨝ ρ g T) ⨝ T1.d = T2.d and T1.b ≠ T2.b ρ T2 ( π v1.b, v1.d ρ v1 S ⨝ ρ g T)

这使用了12个运营商。您可能只想将表的所有实例重命名为不同的名称并将它们连接在一起,而不是在联接内部进行选择!

 SELECT V1.VTitel,
        V2.VTitel,
        VG1.Titel
   FROM Vorlesung AS V1 
   JOIN VG AS VG1
     ON VG1.VNummer = V1.VNummer
   JOIN Vorlesung AS V2
     ON V1.VTitel <> V2.VTitel
   JOIN VG AS VG2
     ON VG2.VNummer = V2.VNummer
  WHERE VG2.Titel = VG1.Titel

这为我们提供了一个更易于管理的9个运营商:

π V1.b, V2.b, V1.d σ VG1.b = VG2.b ρ V1 S ⨝ VG1.d = V1.d ρ VG1 T ⨝ V1.b ≠ V2.b ρ V2 S ⨝ VG2.d = V2.d ρ VG2 T

注意我已经摆脱了自然连接,因此我们不必担心括号等;自然连接在现实生活中也是一种可怕的东西,但在理论上是有意义的。如果您可以使用自然连接重写新查询,并且如果您可以在没有where子句的情况下再次编写它,那么看看您是否理解我所做的是一个很好的练习!