自联接与内部联接

Nil*_*mar -4 sql oracle self-join

自连接和内连接有什么区别

Joh*_*ell 10

我发现将SELECT语句中的所有表都视为表示自己的数据集会很有帮助.

在应用任何条件之前,您可以将每个数据集视为完整(例如,整个表).

连接只是开始优化这些数据集以查找您真正想要的信息的几种方法之一.

虽然数据库模式可能在设计时考虑了某些关系(主键< - >外键),但这些关系实际上只存在于特定查询的上下文中.查询编写者可以将他们想要的任何内容与他们想要的任 我稍后会给出一个例子......


INNER JOIN将两个表相互关联.在一个查询中通常有多个JOIN操作将多个表链接在一起.它可以变得如此复杂.举一个简单的例子,考虑以下三个表......

STUDENT

| STUDENTID | LASTNAME | FIRSTNAME |
------------------------------------
      1     |  Smith   |   John
      2     |  Patel   |  Sanjay
      3     |   Lee    |  Kevin
      4     |  Jackson |  Steven
Run Code Online (Sandbox Code Playgroud)
ENROLLMENT

| STUDENTID | CLASSID |
-----------------------
      2     |    3
      3     |    1
      4     |    2
Run Code Online (Sandbox Code Playgroud)
CLASS

| CLASSID | COURSE | PROFESSOR |
--------------------------------
     1    | CS 101 |   Smith
     2    | CS 201 |  Ghandi
     3    | CS 301 |  McDavid
     4    | CS 401 |  Martinez
Run Code Online (Sandbox Code Playgroud)

STUDENT表和CLASS表旨在通过ENROLLMENT表相互关联.这种表称为连接表.

要编写查询以显示所有学生及其注册的类,将使用两个内部联接...

SELECT stud.LASTNAME, stud.FIRSTNAME, class.COURSE, class.PROFESSOR
FROM STUDENT stud
INNER JOIN ENROLLMENT enr
    ON stud.STUDENTID = enr.STUDENTID
INNER JOIN CLASS class
    ON class.CLASSID = enr.CLASSID;
Run Code Online (Sandbox Code Playgroud)

仔细阅读以上内容,你应该看看发生了什么.您将获得的回报是以下数据集......

 | LASTNAME | FIRSTNAME | COURSE | PROFESSOR |
 ---------------------------------------------
     Patel  |   Sanjay  | CS 301 |  McDavid
      Lee   |   Kevin   | CS 101 |   Smith
    Jackson |  Steven   | CS 201 |  Ghandi
Run Code Online (Sandbox Code Playgroud)

使用JOIN子句,我们将所有三个表的数据集限制为仅相互匹配的数据集."匹配"是使用ON子句定义的.请注意,如果运行此查询,则不会看到CLASS表中的CLASSID 4行或STUDENT表中的STUDENTID 1行,因为匹配中不存在这些ID(在本例中为ENROLLMENT表).查看"LEFT"/"RIGHT"/"FULL OUTER",了解如何使这项工作略有不同.

请注意,根据我之前对"关系"的评论,没有理由不能直接在LASTNAME和PROFESSOR列上运行与STUDENT表和CLASS表相关的查询.这两列匹配数据类型,看看那个!他们甚至有共同的价值!这可能是一个奇怪的数据集来获得回报.我的观点是它可以完成,你永远不知道将来你需要什么才能获得有趣的数据连接.理解数据库的设计,但不要将"关系"视为不可忽视的规则.

在此期间...自我加入!


考虑下表......

PERSON

| PERSONID | FAMILYID |  NAME  |
--------------------------------
      1    |     1    |  John
      2    |     1    | Brynn
      3    |     2    | Arpan
      4    |     2    | Steve
      5    |     2    |  Tim
      6    |     3    | Becca
Run Code Online (Sandbox Code Playgroud)

如果你觉得如此倾向于建立一个你知道的所有人的数据库,以及哪些人在同一个家庭中,那么这可能是它的样子.

如果你想要退回一个人,比如PERSONID 4,你会写...

SELECT * FROM PERSON WHERE PERSONID = 4;
Run Code Online (Sandbox Code Playgroud)

你会得知他和FAMILYID 2家人在一起.然后找到他家里的所有 PERSON,你会写...

SELECT * FROM PERSON WHERE FAMILYID = 2;
Run Code Online (Sandbox Code Playgroud)

做完了!当然,SQL可以在一个查询中使用,您猜对了,SELF JOIN.

真正触发SELF JOIN需求的是该表包含一个唯一列(PERSONID)和一个用作"Category"(FAMILYID)类的列.这个概念称为基数,在这种情况下代表一对多或1:M的关系.只有一个PERSON但也有很多 家庭.

所以,如果一个家庭的PERSONID成员知道,我们想要归还的是一个家庭的所有成员......

SELECT fam.*
FROM PERSON per
JOIN PERSON fam
    ON per.FamilyID = fam.FamilyID
WHERE per.PERSONID = 4;
Run Code Online (Sandbox Code Playgroud)

这是你得到的......

| PERSONID | FAMILYID |  NAME  |
--------------------------------
      3    |     2    | Arpan
      4    |     2    | Steve
      5    |     2    |  Tim
Run Code Online (Sandbox Code Playgroud)

让我们注意几件事.SELF JOIN这个词不会出现在任何地方.那是因为SELF JOIN只是一个概念.上面的查询中的单词JOIN可能是LEFT JOIN,而且会发生不同的事情.SELF JOIN的要点是您使用相同的表两次.

从数据集开始考虑我的肥皂盒.这里我们从PERSON表中开始两次数据集.除非我们这样做,否则数据集的任何一个实例都不会影响另一个实例.

让我们从查询的底部开始.在每个数据集被仅限于那些行,其中PERSONID = 4,知道上表中我们知道,将返回一行.该行中的FAMILYID列的值为2.

在ON子句我们限制FAM数据集(其在这一点上仍是整个PERSON表),只有那些其中FAMILYID的值相匹配的行的一个或多个所述的FAMILYIDs的数据集.正如我们所讨论的,我们知道每个数据集只有一行,因此有一个FAMILYID值.因此,fam数据集现在只包含FAMILYID = 2的行.

最后,在查询的顶部,我们选择fam数据集中的所有行.

瞧!两个查询合二为一.


总之,INNER JOIN是几种JOIN操作之一.我强烈建议进一步阅读LEFT,RIGHT和FULL OUTER JOIN(统称为OUTER JOIN).我个人错过了一次工作机会,因为他对OUTER JOIN的了解很少,不会让它再次发生!

一个自联接简直是任何连接,你是与一个表与自身操作.您选择将该表连接到自身的方式可以使用INNER JOINOUTER JOIN.请注意,使用SELF JOIN,为了不混淆您的SQL引擎,您必须使用表别名(fam和来自上面.构成对您的查询有意义的任何内容)或者无法区分同一个表的不同版本.

既然您了解了这种差异,那么您就可以开始思考,并且可以认识到一个查询可以同时包含所有不同类型的JOIN.这只是您想要的数据以及如何扭曲和弯曲查询以获得它的问题.如果您发现自己运行一个查询并获取该查询的结果并将其用作另一个查询的输入,那么您可以使用JOIN来使其成为一个查询.

要尝试使用SQL,请尝试访问W3Schools.com.这里有一个本地存储的数据库,其中包含一堆表,这些表旨在以各种方式相互关联,并且数据充满了!您可以创建,删除,插入,更新和选择所需的所有内容,并随时将数据库恢复为默认值.尝试各种SQL出来试验不同的技巧.我自己也学到了很多东西.

对不起,如果这有点罗嗦,但当我开始学习SQL并通过使用一堆其他复杂的概念来解释一个概念时,我个人很难接受JOIN的概念.最好从有时开始.

我希望它有所帮助.如果你可以把JOIN放在后面的口袋里,你可以使用SQL来实现魔力!

快乐的查询!