JCC*_*CyC 893 mysql sql join inner-join
为简单起见,假设所有相关字段都是NOT NULL.
你可以做:
SELECT
table1.this, table2.that, table2.somethingelse
FROM
table1, table2
WHERE
table1.foreignkey = table2.primarykey
AND (some other conditions)
Run Code Online (Sandbox Code Playgroud)
要不然:
SELECT
table1.this, table2.that, table2.somethingelse
FROM
table1 INNER JOIN table2
ON table1.foreignkey = table2.primarykey
WHERE
(some other conditions)
Run Code Online (Sandbox Code Playgroud)
这两个是以同样的方式工作MySQL吗?
Qua*_*noi 687
INNER JOIN 是您应该使用的ANSI语法.
它通常被认为更具可读性,尤其是当您加入大量表时.
OUTER JOIN只要有需要,它也可以很容易地替换.
该WHERE语法更关系模型为主.
两个表格的结果JOIN是应用过滤器的表的笛卡尔积,其仅选择具有匹配的连接列的那些行.
使用WHERE语法更容易看到这一点.
至于你的例子,在MySQL(以及一般的SQL)中,这两个查询是同义词.
另请注意,MySQL也有一个STRAIGHT_JOIN子句.
使用此子句,您可以控制JOIN顺序:在外循环中扫描哪个表以及在内循环中扫描哪个表.
你无法使用WHERE语法在MySQL中控制它.
Car*_*ter 173
其他人指出,INNER JOIN有助于人类的可读性,这是首要任务; 我同意.让我试着解释为什么连接语法更具可读性.
一个基本的SELECT查询是这样的:
SELECT stuff
FROM tables
WHERE conditions
Run Code Online (Sandbox Code Playgroud)
SELECT子句告诉我们什么,我们正在找回; FROM子句告诉我们从哪里获取它,WHERE子句告诉我们我们得到了哪些.
JOIN是关于表的声明,它们如何绑定在一起(概念上,实际上,绑定到单个表中).任何控制表的查询元素 - 我们从中获取东西 - 在语义上属于FROM子句(当然,这是JOIN元素所在的位置).将join-elements放入WHERE子句会将which和where-from混合在一起; 这就是JOIN语法首选的原因.
raf*_*een 133
在ON/WHERE中应用条件语句
在这里,我已经解释了逻辑查询处理步骤.
参考:Microsoft®SQLServer™2005内部T-SQL查询
发布者:Microsoft Press
Pub日期:2006年3月7日
打印ISBN-10:0-7356-2313-9
打印ISBN-13:978-0-7356-2313-2
页数:640
内部Microsoft®SQLServer™2005 T-SQL查询
(8) SELECT (9) DISTINCT (11) TOP <top_specification> <select_list>
(1) FROM <left_table>
(3) <join_type> JOIN <right_table>
(2) ON <join_condition>
(4) WHERE <where_condition>
(5) GROUP BY <group_by_list>
(6) WITH {CUBE | ROLLUP}
(7) HAVING <having_condition>
(10) ORDER BY <order_by_list>
Run Code Online (Sandbox Code Playgroud)
与其他编程语言不同的SQL的第一个显着方面是代码的处理顺序.在大多数编程语言中,代码按其编写顺序进行处理.在SQL中,处理的第一个子句是FROM子句,而首先出现的SELECT子句几乎是最后处理的.
每个步骤都会生成一个虚拟表,用作以下步骤的输入.这些虚拟表对调用者(客户端应用程序或外部查询)不可用.只有最后一步生成的表才会返回给调用者.如果查询中未指定某个子句,则只需跳过相应的步骤.
如果步骤的描述现在似乎没有多大意义,请不要太担心.这些是作为参考提供的.在场景示例之后的部分将更详细地介绍这些步骤.
FROM:在FROM子句的前两个表之间执行笛卡尔积(交叉连接),结果生成虚拟表VT1.
ON:ON滤波器应用于VT1.只有<join_condition>TRUE的行插入VT2.
OUTER(join):如果指定了OUTER JOIN(而不是CROSS JOIN或INNER JOIN),则保留的表中未找到匹配项的行将作为外行添加到VT2的行中,从而生成VT3.如果FROM子句中出现两个以上的表,则在最后一个连接的结果和FROM子句中的下一个表之间重复应用步骤1到步骤3,直到处理完所有表.
WHERE:WHERE过滤器应用于VT3.只有<where_condition>TRUE的行插入VT4.
GROUP BY:VT4中的行根据GROUP BY子句中指定的列列表按组排列.VT5已生成.
CUBE | ROLLUP:超级组(组的组)被添加到VT5的行中,生成VT6.
HAVING:HAVING过滤器应用于VT6.只有<having_condition>TRUE的组才会插入VT7.
SELECT:处理SELECT列表,生成VT8.
DISTINCT:从VT8中删除重复的行.生成VT9.
ORDER BY:VT9中的行根据ORDER BY子句中指定的列列表进行排序.生成游标(VC10).
TOP:从VC10的开头选择指定的行数或百分比.生成表VT11并将其返回给调用者.
(在ON/WHERE中应用条件语句在少数情况下不会有太大区别.这取决于您加入的表数和每个连接表中可用的行数)
Cad*_*oux 60
隐式连接ANSI语法较旧,不太明显,不推荐使用.
此外,关系代数允许WHERE子句中的谓词的可互换性INNER JOIN,因此即使INNER JOIN带有WHERE子句的查询也可以使优化器重新排列谓词.
我建议您以最可读的方式编写查询.
有时这包括使INNER JOIN相对"不完整",并WHERE简单地将一些标准放在一起,以使过滤标准列表更容易维护.
例如,而不是:
SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
ON ca.CustomerID = c.CustomerID
AND c.State = 'NY'
INNER JOIN Accounts a
ON ca.AccountID = a.AccountID
AND a.Status = 1
Run Code Online (Sandbox Code Playgroud)
写:
SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
AND a.Status = 1
Run Code Online (Sandbox Code Playgroud)
但这当然取决于它.
mat*_*t b 30
一旦您需要开始向查询添加更多表,隐式连接(这是您的第一个查询被称为)会变得更加混乱,难以阅读和难以维护.想象一下,在四个或五个不同的表上进行相同的查询和连接类型......这是一场噩梦.
使用显式连接(第二个示例)更易读,易于维护.
HLG*_*GEM 25
我还要指出,使用较旧的语法更容易出错.如果在没有ON子句的情况下使用内部联接,则会出现语法错误.如果您使用旧语法并忘记where子句中的一个连接条件,您将获得交叉连接.开发人员经常通过添加distinct关键字(而不是修复连接,因为他们仍然没有意识到连接本身被破坏)来解决这个问题,这似乎可以解决问题,但会大大减慢查询速度.
另外对于维护,如果您使用旧语法进行交叉连接,维护者将如何知道是否有一个(有需要交叉连接的情况)或者是否应该修复的事故?
让我指出这个问题,看看为什么如果你使用左连接,隐式语法是坏的. Sybase*=到Ansi Standard,具有2个不同的外部表用于相同的内部表
加上(个人咆哮),使用显式连接的标准已超过20年,这意味着隐式连接语法已经过时了20年.您是否会使用已经过时20年的语法编写应用程序代码?你为什么要编写数据库代码?
Joh*_*zen 12
它们具有不同的人类可读意义.
但是,根据查询优化器,它们可能与计算机具有相同的含义.
您应始终编写可读代码.
也就是说,如果这是内置关系,请使用显式连接.如果要匹配弱相关数据,请使用where子句.
小智 11
SQL:2003标准更改了一些优先级规则,因此JOIN语句优先于"逗号"连接.这实际上可以根据设置的方式更改查询结果.当MySQL 5.0.12切换到符合标准时,这会给某些人带来一些问题.
因此,在您的示例中,您的查询将起作用.但是如果你添加了第三个表:SELECT ... FROM table1,table2 JOIN table3 ON ... WHERE ...
在MySQL 5.0.12之前,首先连接table1和table2,然后连接table3.现在(5.0.12及以上),首先连接table2和table3,然后连接table1.它并不总是改变结果,但它可以,你可能甚至没有意识到它.
我再也不会使用"逗号"语法了,选择了第二个例子.无论如何,它的可读性要高得多,JOIN条件与JOIN相关,而不是单独的查询部分.