2

所以基本上我正在关注一个教程问题,它问我下面的问题。我不太确定如何加入不包含其他 FK 的 2 个表,它们(即它们的两个 FK)位于第三个表中。我能得到一些帮助/解释吗?

我的答案

SELECT Forest.Fo_name, Species.Sp_name, Species.Sp_woodtype
FROM Forest
INNER JOIN Species
ON Tree.Tr_species=Tree.Tr_forest
WHERE Fo_loc='ARTIC'
ORDER BY Fo_name, Sp_name

“对于在编码为“ARTIC”的区域中发现的森林,列出在其中发现的森林名称和树种名称以及树种木材类型。消除任何重复项并按森林名称和树种名称排序输出

物种表

+--------------+------------------+------+--------------------------------+
| Field        | Type             |  Key | Glossary                       |
+--------------+------------------+------+--------------------------------+
| sp_name      | C(10)            |  PK  | Species Name                   |
| sp_woodtype  | C(10)            |      | Wood Yielded by tree           |
| sp_maxht     |  I               |      | Max. Height                    |
+--------------+------------------+------+--------------------------------+

森林表

+--------------+------------------+------+--------------------------------+
| Field        | Type             |  Key | Glossary                       |
+--------------+------------------+------+--------------------------------+
| Fo_name      | C(10)            |  PK  | Forest Name                    |
| Fo_size      |   I              |      | Forest Area                    |
| Fo_loc       | C(10)            |      | Geographical Area              |
| Fo_comp      | C(10)            |      | Forest Owner                   |
+--------------+------------------+------+--------------------------------+

树形表

+--------------+------------------+------+---------------------------------------------+
| Field        | Type             |  Key | Glossary                                    |
+--------------+------------------+------+---------------------------------------------+
| Tr_species   | C(10)            |  FK  | (FK  of species.sp_name                     |
| Tr_forest    | C(10)            |  FK  | (FK of forest.fo_name                       |
| Tr_numb      |   I              |  PK  | Sequence number                             |
| Tr_planted   | Date             |      | Date of planting                            | 
| Tr_loc       | C(10)            |      | Forest quadrant                             |
| Tr_parent    |   I              |  FK  | (FK of tree.numb) procreating tree reference|
+--------------+------------------+------+---------------------------------------------+

C(10) & I 分别代表字符 (10) & Integer

4

6 回答 6

3

Tree表是 Forest 表和 Species 表之间的连接。把它想象成两个步骤:

1)从Forest表开始,加入Tree表(from Forest.Fo_nameto Tree.Tr_forest

2)既然树是已知的,加入Species表(从Tree.speciesSpecies.sp_name

我会像这样编写最终查询:

SELECT Forest.Fo_name, Species.Sp_name, Species.Sp_woodtype
FROM Forest
JOIN Tree ON Forest.Fo_name=Tree.Tr_forest
JOIN Species ON Tree.species=Species.sp_name
WHERE Fo_loc='ARTIC'
ORDER BY Fo_name, Sp_name
于 2014-05-23T23:05:21.680 回答
3

连接表不需要外键!

因此,当它们之间没有 FK 时如何加入表的答案就是加入它们

真正的问题是我们如何选择加入哪些表(或以任何其他方式组合)?

报表和表格

每个基表都带有一个谓词--statement 模板,由列名参数化。表值是使其谓词成为真实命题--语句的行。

// species [name] yields [woodtype] and has max height [maxht]
Species(name,woodtype,maxht)
// forest [name] has area [size] in area [loc] and owner [comp]
Forest(name,size,loc,comp)
// tree group [numb] is of species [species] in forest [forest] and was planted in [planted] in quadrant [loc] on date [date] with parent tree group [parent]
Tree(species,forest,numb,planted,loc,parent)

查询也有谓词。它的值也是使其谓词为真的行。它的谓词是根据 its 和其他子句建立FROMWHERE。表别名将表值命名为与其基表类似,但列以别名为前缀。所以它的谓词是使用别名前缀列的基表谓词。

Species s

保持行满足

species [s.name] yields [s.woodtype] and has max height [s.maxht]

CROSS & INNER JOIN 在谓词之间放置 AND;UNION 在它们之间放置 OR;除了在条件中插入 AND NOT 和 ON & WHERE AND;SELECT 重命名、添加和删除列。(等其他运营商。)所以

Species s CROSS JOIN Forest f

保存行在哪里

    species [s.name] yields [s.woodtype] and has max height [s.maxht]
AND forest [f.name] has area [f.size] in area [f.loc] and owner [f.comp]

(无论约束是什么!)如果您只希望上面的行具有以其木材类型命名的森林,那么您只需添加一个条件 via ,... WHERE f.name=s.woodtype因为这会使值成为满足的行... AND f.name=s.woodtype

对于在编码为“北极”的地区发现的森林,请列出在其中发现的森林名称和物种名称以及物种木材类型。消除任何重复并按森林名称和物种名称对输出进行排序。

这是返回的行要满足的一个很大的非正式谓词。如果我们尝试仅使用给定的谓词加上 AND、OR、AND NOT (等)来重写它,那么我们只能通过AND对所有三个给定的谓词(因此,JOIN基表名称)和添加AND Forest.loc='ARCTIC'(因此,ONWHERE那个条件)。

FK(等)和查询(不)

PK 和 FK 是完整性约束的特殊情况。给定谓词和可能出现的情况,只能出现一些数据库值。这就是完整性约束所描述的。他们让 DBMS 将不应该出现的数据库值排除在外。(另外,优化查询执行。)因为名称在 Species 中是唯一的,所以我们将其声明为键。森林名称和树麻木同上。因为 Tree 中的物种是 Species 中的名称,而名称是 Species 的键,所以我们声明 FK Tree.species->Species.name。森林和父母同上。与启用联接无关。(尽管它们暗示查询结果也满足某些约束。)

查询约束是什么并不重要。如果存在由于业务规则或树或物种谓词不同而未显示为任何物种名称值的树物种值,则将没有 FK Tree.species->Species.name。但是每个查询将继续返回满足其谓词的行,这些行以基表谓词表示。(由于可能的业务情况或谓词不同,输入行可能不同,因此输出行可能不同。)

什么决定了查询 SQL

因此,我们如何选择要加入(或以任何其他方式组合)哪些表的答案是,我们适当地安排基表名称、JOIN、UNION、EXCEPT 和 WHERE(等),以给出一个查询表达式,其谓词是我们的谓词。希望我们的行满足。这通常被认为是非正式的,可以通过感觉来完成,但现在您知道 SQL 与自然语言的联系了。约束是无关紧要的。

注意:前面假设我们没有从查询中返回重复项。之所以在关系模型中表中没有重复,是因为上面的表操作符和逻辑连接符的对应关系成立。但是 SQL 表可以有重复项。在 SQL 与关系模型不同的地方(在很多方面),查询变得不那么合乎逻辑。

重新连接以下外键
重新选择表
是否有任何经验法则可以根据人类可读的描述构造 SQL 查询?

于 2014-05-24T06:40:19.397 回答
1

你可以做多个连接。将树表链接到主表森林,然后链接物种表:

SELECT 
Forest.Fo_name, 
Species.Sp_name, 
Species.Sp_woodtype

FROM 
Forest
INNER JOIN Tree ON Tree.Tr_forest=Forest.Fo_name
INNER JOIN Species ON Tree.Tr_species = Species.sp_name

WHERE 
Fo_loc='ARTIC'

ORDER BY Fo_name, Sp_name
于 2014-05-23T23:05:01.480 回答
1

尝试 SQL 99 方法

      SELECT DISTINCT F.Fo_name, S.Sp_name, Sp_woodtype
      FROM Forest F, Species S, Tree T
      WHERE F.Fo_name = T.Tr_Forest 
      AND S.Sp_name = Tr_species
      AND f.Fo_loc = 'ARCTIC';

AFS 是用于使 SQL 更短、更整洁的别名。

DISTINCT 将删除重复项。

于 2014-05-23T23:08:03.170 回答
0

ON条件应该比较来自不同表的列。

然后,您只需逐步加入每个表。

SELECT DISTINCT Fo_name, Sp_name, Sp_woodtype
FROM Forest AS f
INNER JOIN Tree AS t ON t.Tr_forest = f.Fo_name
INNER JOIN Species AS s ON t.Tr_speecies = s.Sp_name
WHERE f.Fo_loc = 'ARCTIC'
ORDER BY Fo_name, Sp_name
于 2014-05-23T23:05:17.973 回答
0
SELECT Forest.Fo_name, Species.Sp_name, Species.Sp_woodtype
    FROM Forest
        INNER JOIN Tree 
            INNER JOIN Species ON Species.sp_name = Tree.Tr_species
        ON Forest.Fo_name=Tree.Tr_forest
WHERE Fo_loc='ARTIC'
ORDER BY Fo_name, Sp_name
于 2014-05-23T23:07:00.110 回答