mysql 将两个表及其FK合并到第三个表中,但彼此不合并

pokxtpni  于 12个月前  发布在  Mysql
关注(0)|答案(6)|浏览(100)

一个教程问题:
对于在“北极”地区发现的森林,请列出森林名称、树种名称和其中发现的树种木材类型。消除任何重复,并按森林名称和树种名称排序输出。
物种
| 领域|类型|关键|术语表|
| --|--|--|--|
| 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

字符串

imzjd6km

imzjd6km1#

连接表不需要外键!
因此,当表之间没有FK时,如何连接表的答案是 * 只是连接它们
真实的问题是 * 我们如何选择连接哪些表(或以任何其他方式合并)?

报表和表格

每个基表都带有一个由列名参数化的 predicate--statement模板。表值是使其 predicate 成为真 proposition--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)

字符串
查询也有一个 predicate 。它的值也是使其 predicate 为true的行。它的 predicate 是根据它的FROMWHERE和其他子句构建的。表别名命名表值,就像它的基表一样,但列以别名为前缀。因此,它的 predicate 是它的基表的 predicate ,使用别名前缀列。

Species s


保持行满足

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


CROSS & INNER JOIN在 predicate 之间放置AND; UNION在 predicate 之间放置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]


(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'(因此,ONWHERE该条件)来完成。

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?

eh57zj3b

eh57zj3b2#

Tree表是Forest表和Species表之间的连接。将其视为两个步骤:
1)从Forest表开始,连接到Tree表(从Forest.Fo_nameTree.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

字符串

rta7y2nd

rta7y2nd3#

您可以执行多个联接。将树表链接到主表森林,然后链接物种表:

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

字符串

zzzyeukh

zzzyeukh4#

使用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';

字符串
F S是用来使SQL更短更整洁的别名。
DISTINCT将删除重复。

zz2j4svz

zz2j4svz5#

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

字符串

o2gm4chl

o2gm4chl6#

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

字符串

相关问题