以下两个查询给出相同的结果.只是想知道哪一个在性能方面更好.
查询1:
SELECT N.*
FROM NOTIFICATIONS N
JOIN NOTIFICATION_COMPANY_GROUPS NCG
ON ( N.COMPANY_ID = NCG.COMPANY_ID
AND N.ID = NCG.NOTIFICATION_ID )
JOIN COMPANY_USER_GROUPS CUG
ON ( N.COMPANY_ID = CUG.COMPANY_ID
AND CUG.COMPANY_GROUP_ID = NCG.COMPANY_GROUP_ID )
JOIN NOTIFICATION_PROPERTIES NP ON ( N.COMPANY_ID = NP.COMPANY_ID )
JOIN COMPANY_USER_PROPERTIES CUP
ON ( N.COMPANY_ID = CUP.COMPANY_ID
AND CUP.PROPERTY_ID = NP.PROPERTY_ID )
WHERE N.COMPANY_ID = 2138
AND CUG.COMPANY_USER_ID = 41422
AND CUP.COMPANY_USER_ID = 41422;
Run Code Online (Sandbox Code Playgroud)
查询2:
SELECT N.*
FROM NOTIFICATIONS N
JOIN NOTIFICATION_COMPANY_GROUPS NCG
ON ( N.COMPANY_ID = 2138
AND N.COMPANY_ID = NCG.COMPANY_ID
AND N.ID = NCG.NOTIFICATION_ID )
JOIN COMPANY_USER_GROUPS CUG
ON ( CUG.COMPANY_USER_ID = 41422
AND N.COMPANY_ID = CUG.COMPANY_ID
AND CUG.COMPANY_GROUP_ID = NCG.COMPANY_GROUP_ID )
JOIN NOTIFICATION_PROPERTIES NP ON ( N.COMPANY_ID = NP.COMPANY_ID )
JOIN COMPANY_USER_PROPERTIES CUP
ON ( CUP.COMPANY_USER_ID = 41422
AND N.COMPANY_ID = CUP.COMPANY_ID
AND CUP.PROPERTY_ID = NP.PROPERTY_ID );
Run Code Online (Sandbox Code Playgroud)
我希望性能应该相同,但您可以EXPLAIN用来验证查询计划是否相同.
但是,第一个版本是编写它的"正确"方式.通常,ON子句应该只包含与作为连接的表相关的条件,而单个表的条件应该在WHERE子句中.
唯一的例外是在LEFT JOIN子句中,表中的条件应该在ON子句中.这是因为如果将它们放在WHERE子句中,除非您明确检查,否则将过滤掉主表中没有匹配项的行中的空行NULL.举个例子:
SELECT ...
FROM T1
LEFT JOIN T2 ON T2.T1_id = T1.id AND T2.someCol = 3
Run Code Online (Sandbox Code Playgroud)
与
SELECT ...
FROM T1
LEFT JOIN T2 ON T2.T1_id = T1.id
WHERE T2.someCol = 3
Run Code Online (Sandbox Code Playgroud)
在第一个版本中,测试T2.someCol是在加入之前完成的; 结果将包含所有行T1,但没有匹配的那些排在T2将NULL所有T2列.但是第二个版本不会有任何这些不匹配的行,因为首先完成连接,然后它执行T2.someCol = 3测试; 如果没有匹配的T2行,T2.someCol将会NULL,并且此测试将失败并且该行将被过滤掉WHERE.
在内连接的情况下,无论是在连接之前还是之后进行比较,结果都是等效的.查询计划程序应以最有利于索引的方式对这些进行排序.