6

假设我有一个名为 FISH 的 mysql 表,其中包含字段 A、B 和 C。

我跑SELECT * FROM FISH。这让我对所有领域都有了解。那么,如果 A 是原始表中的键,那么它也是视图中的键吗?意思是,如果我有一张桌子 FISH2,我跑了

 SELECT * FROM (SELECT * FROM FISH) D, (SELECT * FROM FISH2) E WHERE D.A = E.A

相关字段仍然是键吗?

现在,让我们更进一步。如果我跑

SELECT * FROM (SELECT CONCAT(A,B) AS DUCK, C FROM FISH) D, (SELECT CONCAT(A,B) AS DUCK2, C FROM FISH2) E WHERE D.DUCK = E.DUCK2

如果 A 和 B 是原始表中的键,那么它们的连接也是键吗?

谢谢 :)

4

3 回答 3

2

如果A是 中的一个键fish,则仅对鱼的任何投影都会产生一个结果集,其中 A 仍然是唯一的。

表 fish 和任何具有 1:1 关系的表(例如 fish_type)之间的连接将产生一个结果集,其中 A 是唯一的。

与来自鱼的具有 1:M 或 M:M 关系的另一个表(例如 fish_beits)的连接不会产生 A 唯一的结果,除非您在“其他”端(例如bait='Dynamite')提供过滤谓词。

SELECT * FROM (SELECT * FROM FISH) D, (SELECT * FROM FISH2) E WHERE D.A = E.A

...在逻辑上等同于以下语句,大多数数据库(包括 MySQL)都会执行转换:

select *
  from fish
  join fish2 on(fish.a = fish2.a)

A 在结果集中是否仍然唯一取决于 的键fish2及其关系(见上文)。

串联不会保留唯一性。考虑以下情况:

concat("10", "10") => "1010"
concat("101", "0") => "1010"

因此,您的最终查询...

SELECT * 
  FROM (SELECT CONCAT(A,B) AS DUCK, C FROM FISH) D
      ,(SELECT CONCAT(A,B) AS DUCK2, C FROM FISH2) E 
 WHERE D.DUCK = E.DUCK2

...不会(必然)产生与

select * 
  from fish 
  join fish2 on(
       fish.a = fish2.a
   and fish.b = fish2.b
  )

我之所以写必然是因为碰撞取决于实际值。大约前一段时间,我发现了一个错误,其根本原因正是这个。在错误出现之前,代码已经运行了几年。

于 2011-03-20T21:10:50.930 回答
0

如果“键”是指“唯一”,是的,笛卡尔积的唯一值元组将是唯一的。(可以通过归约法证明这一点。)

于 2011-03-20T15:59:27.407 回答
0

对于第 1 步,将视图视为子查询,其中包含执行AS时子句中的所有内容CREATE VIEW

例如,如果视图v创建为SELECT a, b, c FROM t,那么当您执行...

SELECT * FROM v WHERE a = some_value

...它在概念上被视为...

SELECT * FROM (SELECT a, b, c FROM t) WHERE a = some_value

任何具有良好优化器的数据库都会注意到该列a被直接传递到结果中,并且它可以通过将其移动到子查询中来利用索引t(如果有的话):

SELECT * FROM (SELECT a, b, c FROM t WHERE a = some_value)

这一切都发生在幕后,而不是您需要自己做的优化。显然,它不能WHERE对子句中的每个条件都这样做,但了解你可以在哪里是编写一个好的优化器的艺术的一部分。

对于第 2 步,连接的键将成为中间结果的一部分,数据库是否决定它们需要索引是一个实现细节。另请注意 fche 关于重复的评论。

如果您的数据库有一个查询计划解释器,运行它并学习解释结果将使您深入了解是什么让您的查询运行得快,什么让它们变慢。

于 2011-03-20T16:34:22.290 回答