[英]Required to join 2 tables with their FKs in a 3rd table
所以基本上我正在关注一个教程问题,它问我以下问题。 我不太确定如何加入不包含其他 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
Tree
表是 Forest 表和 Species 表之间的连接。 把它想象成两个步骤:
1)从 Forest 表开始,加入Tree
表(从Forest.Fo_name
到Tree.Tr_forest
)
2) 现在树是已知的,加入Species
表(从Tree.species
到Species.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
连接表不需要外键!
因此,当表之间没有 FK 时如何连接表的答案是仅连接它们。
真正的问题是我们如何选择加入哪些表(或以任何其他方式合并)?
报表和表格
每个基表都带有一个由列名参数化的谓词--statement 模板。 表值是使其谓词成为真命题--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)
一个查询也有一个谓词。 它的值也是使其谓词为真的行。 它的谓词是根据它的FROM
、 WHERE
和其他子句构建的。 表别名为其基表命名表值,但列以别名为前缀。 所以它的谓词是使用别名前缀列的基表谓词。
Species s
保持行满足
species [s.name] yields [s.woodtype] and has max height [s.maxht]
CROSS & INNER JOIN 将 AND 放在谓词之间; UNION 在它们之间放置 OR; EXCEPT 在条件中插入 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]
(无论约束是什么!)如果你只想要上面的行以它们的木材类型命名,那么你只需添加一个条件通过... WHERE f.name=s.woodtype
因为这使得值满足行... AND f.name=s.woodtype
。
对于在编码为“北极”的地区发现的森林,请列出其中发现的森林名称和物种名称以及物种木材类型。 消除任何重复项并按森林名称和物种名称对输出进行排序。
这是返回的行要满足的一个很大的非正式谓词。 如果我们尝试仅使用给定的谓词加上 AND、OR、AND NOT(等)来重写它,那么我们只能通过对所有三个给定谓词进行AND
JOIN
(因此,基表名称的JOIN
)并添加AND Forest.loc='ARCTIC'
(因此, ON
或WHERE
条件)。
FK(等)和查询(不是)
PK 和 FK 是完整性约束的特殊情况。 给定谓词以及可能出现的情况,只能出现一些数据库值。 这就是完整性约束所描述的。 它们让 DBMS 将不应出现的数据库值排除在外。 (此外,优化查询执行。)因为名称在 Species 中是唯一的,所以我们将其声明为键。 森林名称和树麻木同上。 因为树中的物种是物种中的名称,而名称是物种的键,所以我们声明 FK Tree.species->Species.name。 森林和父母同上。 与启用连接无关。 (尽管它们暗示查询结果也满足某些约束。)
查询约束是什么并不重要。 如果由于业务规则或 Tree 或 Species 谓词不同而没有显示为任何 Species 名称值的树种值,那么将没有 FK Tree.species->Species.name。 但是每个查询将继续返回满足其谓词的行,如用基表谓词表示的那样。 (由于可能的业务情况或谓词不同,因此输入行可能不同,因此输出行也可能不同。)
什么决定了查询 SQL
因此,我们如何选择要加入的表(或以任何其他方式组合)的答案是我们根据需要安排基表名称、JOIN、UNION、EXCEPT 和 WHERE(等),以给出一个查询表达式,其谓词是我们的谓词。希望我们的行满足。 这通常被教授为通过感觉来完成的非正式的事情,但现在您知道是什么将 SQL 与自然语言联系起来了。 并且约束是无关紧要的。
注意:前面假设我们从查询中没有返回重复项。 关系模型中表中没有重复的原因是为了使表运算符和逻辑连接词之间的上述对应关系成立。 但是,SQL 表可以有重复项。 SQL 不同于关系模型(在很多方面)的地方,查询变得不那么(字面上)逻辑。
您可以进行多个连接。 将树表链接到主表森林,然后链接物种表:
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
尝试 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 将删除重复项。
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
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.