一个教程问题:
对于在“北极”地区发现的森林,请列出森林名称、树种名称和其中发现的树种木材类型。消除任何重复,并按森林名称和树种名称排序输出。
物种
| 领域|类型|关键|术语表|
| --|--|--|--|
| sp_name|中文(简体)|PK|物种名称|
| SP木版|中文(简体)||树木产生的木材|
| sp_maxht|整数||最大高度|
森林
| 领域|类型|关键|术语表|
| --|--|--|--|
| Fo名称|中文(简体)|PK|林名称|
| Fo_size|整数||林区|
| Fo_loc|中文(简体)||地理区域|
| Fo_comp|中文(简体)||森林所有者|
树
| 领域|类型|关键|术语表|
| --|--|--|--|
| Tr_species|中文(简体)|FK|(物种.sp_name的FK|
| Tr_林|中文(简体)|FK|(forest.fo_name的FK|
| Tr_number|整数|PK|序列号|
| Tr_planted|日期||种植日期|
| Tr_loc|中文(简体)||森林象限|
| Tr_parent|整数|FK|(tree.numb的FK)正在生成树引用|
我不知道如何连接两个不包含另一个FK的表--它们的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
字符串
6条答案
按热度按时间imzjd6km1#
连接表不需要外键!
因此,当表之间没有FK时,如何连接表的答案是 * 只是连接它们 。
真实的问题是 * 我们如何选择连接哪些表(或以任何其他方式合并)?
报表和表格
每个基表都带有一个由列名参数化的 predicate--statement模板。表值是使其 predicate 成为真 proposition--statement的行。
字符串
查询也有一个 predicate 。它的值也是使其 predicate 为true的行。它的 predicate 是根据它的
FROM
,WHERE
和其他子句构建的。表别名命名表值,就像它的基表一样,但列以别名为前缀。因此,它的 predicate 是它的基表的 predicate ,使用别名前缀列。型
保持行满足
型
CROSS & INNER JOIN在 predicate 之间放置AND; UNION在 predicate 之间放置OR; EXCEPT在条件中插入AND NOT和ON & WHERE AND; SELECT重命名,添加和删除列。(其他操作符等等。)所以
型
保存行,其中
型
(No不管约束是什么!)如果你只想让上面的行拥有以其木材类型命名的森林,那么你只需要通过
... WHERE f.name=s.woodtype
添加一个条件,因为这使得值是满足... AND f.name=s.woodtype
的行。对于在“北极”地区发现的森林,请列出森林名称和树种名称以及其中发现的树种木材类型。删除任何重复项,并按森林名称和树种名称排序。
这是一个很大的非正式 predicate ,返回的行要满足它。如果我们试图只使用我们已经给出的 predicate 加上AND,OR,AND NOT(等等)重写它,那么我们只能通过
AND
ing所有三个给定的 predicate (因此,基本表名的JOIN
)并添加AND Forest.loc='ARCTIC'
(因此,ON
或WHERE
该条件)来完成。FK(etc)和查询(not)
PK和FK是完整性约束的特殊情况。给定 predicate 和可能出现的情况,只有一些数据库值可以出现。这就是完整性约束所描述的。它们让DBMS将不应该出现的数据库值排除在外。(此外,优化查询执行。)因为一个名字在物种中是唯一的,我们声明它是一个键。森林的名字和树的编号也是如此。因为树中的物种是物种中的一个名字,名字是物种的一个键,我们declare FK Tree.species-> Species. name。对forest和parent也是如此。与启用连接无关。(尽管它们也暗示查询结果满足某些约束。)
查询 * 约束是什么并不重要。如果由于业务规则或Tree或Species predicate 不同,Tree species值没有显示为任何Species名称值,则不会有FK Tree.species-> Species. name。但每个查询将继续返回满足其 predicate * 的行,如根据基表 predicate * 所表示的。(由于可能的业务情况或 predicate 可能不同,因此输入行可能不同,因此输出行也可能不同。)
什么决定查询SQL
因此,我们如何选择要连接(或以任何其他方式合并)的表的答案是,我们适当地安排基表名,JOIN,UNION,EXCEPT和WHERE(等),以给予一个查询表达式,其 predicate 是我们希望我们的行满足的 predicate 。这通常是通过feel进行的非正式教学,但现在你知道SQL与自然语言的联系是什么了。约束是无关紧要的。
注意事项:前面的假设我们从查询中没有返回重复的数据。在关系模型中表中没有重复数据的原因是表操作符和逻辑连接符之间的上述对应关系成立。然而SQL表可以有重复数据。SQL与关系模型的不同之处(在许多方面),查询变得不那么逻辑。
Re joins following foreign keys
Re choosing tables的
Is there any rule of thumb to construct SQL query from a human-readable description?的
eh57zj3b2#
Tree
表是Forest表和Species表之间的连接。将其视为两个步骤:1)从Forest表开始,连接到
Tree
表(从Forest.Fo_name
到Tree.Tr_forest
)2)现在树已经知道了,连接到
Species
表(从Tree.species
到Species.sp_name
)我会这样写最后一个查询:
字符串
rta7y2nd3#
您可以执行多个联接。将树表链接到主表森林,然后链接物种表:
字符串
zzzyeukh4#
使用SQL 99方法
字符串
F S是用来使SQL更短更整洁的别名。
DISTINCT将删除重复。
zz2j4svz5#
ON
条件应该比较来自不同表的列。然后,您只需一步一步地连接每个表。
字符串
o2gm4chl6#
字符串