一尘不染

我会误会加入吗?

sql

我正在尝试学习ansi-92 SQL标准,但是我似乎并不完全了解它(我也是ansi-89标准的新手,并且在数据库中也是新手)。

在我的示例中,我有三个表王国-<家族-<物种(生物学分类)。

  • 可能有没有物种或家庭的王国。
  • 可能有一些家庭没有物种或种类。
  • 可能有没有王国或家庭的物种。

为什么会发生这种情况?

一位生物学家说,找到了一个新物种,但他没有将其分类为一个王国或家庭,创建了一个没有物种并且不确定该属于哪个王国的新家庭,等等。

这是一个小提琴(请参阅最后一个查询):http :
//sqlfiddle.com/#!4/015d1/3

我想查询一个检索到我每个王国,每个物种的信息,而不是检索那些没有物种的家庭的信息,因此,我这样做了。

    select *
    from reino r
         left join (
             familia f             
             right join especie e
                 on f.fnombre = e.efamilia
                 and f.freino = e.ereino
         ) on r.rnombre = f.freino 
           and r.rnombre = e.ereino;

我认为这样做是:

  1. 作为正确的联接加入家庭和物种,因此它带来了每个物种,但没有带来那些没有物种的家庭。因此,如果某个物种尚未归类,则其在家族中将显示为空。

  2. 然后,以左连接的形式加入王国,这样即使没有该王国上的任何家族或物种,它也带给每个王国。

我错了吗?这不应该告诉我那些尚未分类的物种吗?如果我进行内部查询,它将带来我想要的东西。我在对事物进行分组时存在问题吗?


阅读 124

收藏
2021-05-23

共1个答案

一尘不染

您对#1的描述是正确的…查询问题在步骤#2上。

当您进行leftjoin从王国到(家庭和物种)的交易时,即使没有匹配的(家庭和物种),您也要请求每个王国…但是,这不会返回任何不符合您要求的(家庭和物种)组合没有匹配的王国。

一个更接近的查询将是:

select *
    from reino r
         full join (
             familia f             
             right join especie e
                 on f.fnombre = e.efamilia
                 and f.freino = e.ereino
         ) on r.rnombre = f.freino 
           and r.rnombre = e.ereino;

请注意,将left join替换为full join

但是,这仅返回与某个物种相关联的家庭……它不返回与该王国相关联的任何家庭,而不返回任何与物种相关联的家庭。

重新阅读您的问题后,这实际上是您想要的…


编辑:经过进一步的思考,您可以像这样重新编写查询:

select *
from 
    especie e
    left join familia f 
        on f.fnombre = e.efamilia
        and f.freino = e.ereino
    full join reino r
        on r.rnombre = f.freino 
        and r.rnombre = e.ereino;

我认为这是可取的,因为您消除了RIGHT JOIN通常由于风格不佳而被皱眉的…和括号,这对于人们正确解析以确定结果将是棘手的。

2021-05-23