有一些关于连接交换的StackOverflow的讨论,例如1,2,3和4。这变得非常复杂,我想他们中没有人在这里回答我的问题。
我经常注意到,当我将查询的SQL放入Access时,Access弄乱了我的联接顺序,甚至将LEFT
联接更改为RIGHT
。我通常将外部联接写为LEFT
,在逻辑上布置联接表的顺序,因此当Access将其弄乱时,我不喜欢它。但是现在我注意到在设计视图中查询的表示方式有所不同,我想知道这种差异是否显着。
这是三个查询:
Query1
SELECT Table1.ID_Table1
FROM Table2 RIGHT JOIN (Table1 LEFT JOIN Table12
ON Table1.ID_Table1 = Table12.ID_Table1) ON Table2.ID_Table2 = Table12.ID_Table2;
Query2
SELECT Table1.ID_Table1
FROM Table1 LEFT JOIN (Table2 RIGHT JOIN Table12
ON Table2.ID_Table2 = Table12.ID_Table2) ON Table1.ID_Table1 = Table12.ID_Table1;
Query3
SELECT Table1.ID_Table1
FROM Table1 LEFT JOIN (Table12 LEFT JOIN Table2
ON Table12.ID_Table2 = Table2.ID_Table2) ON Table1.ID_Table1 = Table12.ID_Table1;
我更喜欢Query3,因为它具有我提到的逻辑顺序。
当我以SQL输入这些查询时,Access将Query2的代码更改为与Query1相同,并且它没有修改Query1或Query3的代码。当运行三个查询(使用非常简单的数据,因此不是决定性的)时,它们都会产生相同的结果。在设计视图中,Query1和Query2看起来相同,这很好,因为Access将Query2转换为Query1。 Query3看起来几乎相同,除了在Query1和Query2的视图中表示的Table2和Table12之间的关系在Query3的视图中未表示。
所以我的问题是,Query3是否等效于Query1和Query2,因此可以安全地忽略在Design View中表关系表示的丢失,或者查询中是否存在操作上的差异?如果存在差异,是否有指导联接顺序的原则?
答案 0 :(得分:1)
这不是答案,而是注释部分中不适合的注释。
...访问混乱了我的连接顺序,甚至将LEFT连接更改为RIGHT连接...
好吧,事实是SQL是一种声明性语言。与诸如C,C ++,Java,PHP等命令性语言不同,您没有指定如何检索所需的数据,而是告诉SQL引擎所需的内容。
当您运行SQL语句时,数据库引擎将在几个“阶段”中处理查询,包括解析,缓存,应用参数,重述,计划,优化,执行,管道,交付等。每个数据库引擎都会添加我提到的阶段更多。
对此问题感兴趣的是措辞,计划和优化。
引擎经常会重新定义SQL以便更好地管理它。引擎开发人员决定,如果将引擎的计划写成“颠倒”,可能会有100万个原因使引擎可以更好地管理计划。您无法真正控制它。有时候,您有可以理解的真正正当理由;有时它与数据库引擎的内部组织有关。
然后,SQL计划者考虑您提到的表,指定的过滤条件,现有索引,表的统计信息(最新或过时),并生成一组计划。所有这些计划都会产生有效的结果。
然后将这套计划提供给优化器,该优化器将评估成本(经过的时间,磁盘I / O,内存消耗,网络带宽等),并选择“最佳”方案。最好的知识。请考虑,据其所知可能相当la脚,这取决于优化程序的弱小或出色程度,而且通常情况下,所选的“最佳”计划可能不是最大的。< / p>
现在,现实的是,MS-Access绝对不是最大的数据库引擎。您可能希望SQL计划程序和优化程序并不出色。他们可以完成自己的工作,但是它们是为少量数据而不是数百万行而设计的。
最底线,不要指望执行计划将完全匹配您键入的内容。 SQL是一种声明性语言,优化器可以根据需要自由地重写和处理查询,从而以有效和安全的方式存储和检索数据。