好的,这是有点理论性的,所以如果一个公正的数据库爱好者发表意见,那就太好了。
为了便于论证,我们同意存在这样一个概念,即查询的"基表"w.r.t.,其中一个表驱动结果集的大部分信息。想象一个查询,其中有三个关系-表a、表B和表C
假设TableA的基数为100万条记录,TableC有500条记录,而TableC有10000条记录。
假设查询是这样的-
SELECT A.Col1
, A.Col2
, A.Col3
, A.Col4
, A.Col5
FROM TableA A
LEFT JOIN TableB B ON B.ID = A.TableBID
LEFT JOIN TableC C ON C.ID = A.TableCID
好的,显然表A是上面的基本关系。它是最大的表,它通过连接"from"来驱动结果集,从视觉上看,列甚至在结果集的"左侧"。(左边的东西实际上是我同事的一个标准)。
现在,让我们再次假设TableA有100万行,TableB是一个"连接"或"桥接"表,大约有50万行,而TableC有100万列。因此,假设查询只是一个外部联接,以获取TableA和TableC中存在关系的所有列,如下所示。。。
SELECT A.*
, C.*
FROM TableC C
FULL OUTER JOIN TableB B ON C.ID = B.TableAID
FULL OUTER JOIN TableA A ON A.ID = B.TableCID
好的,考虑到最后一个问题,有人能告诉我"基本关系"是什么吗?我不认为有,但希望另一个数据库的人的意见。
术语"基表"有一个定义,它与您描述的内容无关。"基本表"实际上只是一张"表"。也就是说,它不是视图,不是表值函数,也不是查询的结果。它是作为显式表存储在数据库中的内容。
你所掌握的似乎更多地与优化策略有关。在优化的上下文中,我使用了类似的术语来描述优化器访问的"驱动表"。这样做的目的是区分不同的执行计划。
考虑查询:
from t1 join t2 using (col)
有多种不同的执行计划。以下是一些方法以及可能被视为它们的"驱动表"(如果有的话):
for each row in t1
for each row in t2
compare col
--> t1 is the "driving table"
for each row in t2
for each row in t1
compare col
--> t2 is the "driving table"
for each row in t1
look up t2 value using index on t2(col)
--> t1 is the "driving table"
sort t1 by col
sort t2 by col
compare the rows in the two sorted sets
--> no "driving table"
hash t1 by col
hash t2 by col
compare the hash maps
--> no "driving table"
换句话说,"驱动"表与查询结构关系不大。它基于用于查询的优化策略。也就是说,left join
s和right join
s限制了优化路径。因此,在嵌套循环或索引查找的情况下,"第一个"(或"最后一个")表将是驱动表。
"驱动"表的概念实际上是关于DBMS如何在内部执行查询的假设。基于规则的查询优化器在没有任何与索引相关的首选项的情况下,在选择执行计划时,可能会将查询中表和联接的排序视为重要的。在基于成本的优化器下,表和联接的顺序没有任何意义,因此查询本身的结构不会告诉您先读取哪个表,或者按照什么顺序评估联接条件。
在概念化查询时,将一个表作为查询的起点可能会有所帮助,但我认为这里问题的答案一定是否定的。从逻辑上讲,没有驱动表这回事。
基表是一个给定的命名表值变量——一个数据库表。就是这样。在查询表达式中,它的名称是表示其值的叶表达式。"给定表变量"将更具描述性。查询可以对表使用文字表示法。将给定的命名表值常量也称为"基"是合理的。这与某种"主"桌子无关。
关系模型建立在一个表上,该表包含从其(特征)谓词(由列名参数化的语句模板)构成真正命题的行。我们给基表行&获取查询表达式行。
作为基表名称的查询表达式附带由设计器给定的谓词。
/* (person, liked) rows where [liker] likes [liked] */ /* (person, liked) rows where Likes(liker, liked) */ SELECT * FROM Likes
作为表文字的查询表达式在列等于值方面具有特定的谓词。
/* (person) rows where
person = 'Bob'
*/
SELECT * FROM (VALUES ('Bob')) dummy (person)
否则,查询表达式将根据其关系运算符由其组成表表达式谓词构建一个谓词。
- 每个代数运算符都对应于某个逻辑运算符
NATURAL JOIN
&AND
RESTRICT
theta
&AND
theta
UNION
&OR
MINUS
&AND NOT
PROJECT
all but
C
&EXISTS C
etc
/* (person) rows where (FOR SOME liked, Likes(person, liked)) OR person = 'Bob' */ SELECT liker AS person FROM Likes UNION VALUES ('Bob')
/* (person, liked) rows where FOR SOME [values for] l1.*, l2.*, person = l1.liker AND liked = l2.liked AND Likes(l1.liker, l1.liked) AND Likes(l2.liker, l2.liked) AND l1.liked = l2.liker AND person = 'Bob' AND NOT Likes(l1.liked, 'Ed') */ Likes l1 INNER JOIN Likes l2 ON l1.liked = l2.liker WHERE l1.liker = 'Bob' AND NOT (l1.liked, 'Ed') IN (SELECT * FROM Likes)
在确定包含查询表达式的谓词时,如何使用基、文字或运算符调用查询表达式没有区别。
根据人类可读的描述构造SQL查询有什么经验法则吗
关系代数-重新编码列值
让我提出一个透视图,其中基表是FROM
子句中的第一个(即不是JOIN
ed表)。在一个语句可以用一个表或另一个表作为基表来平等地编写的情况下,我们可以说有两个(或多个)基表。
在第一个查询中,基表是TableA
。如果在查询中反转TableA
和TableC
,则不能保证得到相同的结果,因为LEFT JOIN
。
在第二个查询中,当您使用FULL JOIN
s时,所有3个表都可以反转而不更改结果,因此这确实是查询的一个用例,其中所有表都是基表。