在JOIN的ON子句中为哪些方式订购条件是否重要?
select a.Name, b.Status from a
inner join b
on a.StatusID = b.ID
与
select a.Name, b.Status from a
inner join b
on b.ID = a.StatusID
对性能有影响吗?如果我有多个标准怎么办?
一个订单比另一个订单更易于维护吗?
答案 0 :(得分:32)
JOIN
可以通过在FROM
子句中按正确顺序放置表来强制执行命令:
MySQL有一个名为STRAIGHT_JOIN
的特殊条款,它使订单无关紧要。
这将使用b.id
上的索引:
SELECT a.Name, b.Status
FROM a
STRAIGHT_JOIN
b
ON b.ID = a.StatusID
这将使用a.StatusID
上的索引:
SELECT a.Name, b.Status
FROM b
STRAIGHT_JOIN
a
ON b.ID = a.StatusID
Oracle有一个特殊提示ORDERED
来强制执行JOIN
命令:
这将使用b.id
上的索引或在b
上构建哈希表:
SELECT /*+ ORDERED */
*
FROM a
JOIN b
ON b.ID = a.StatusID
这将使用a.StatusID
上的索引或在a
上构建哈希表:
SELECT /*+ ORDERED */
*
FROM b
JOIN a
ON b.ID = a.StatusID
SQL Server有一个名为FORCE ORDER
的提示来执行相同的操作:
这将使用b.id
上的索引或在b
上构建哈希表:
SELECT *
FROM a
JOIN b
ON b.ID = a.StatusID
OPTION (FORCE ORDER)
这将使用a.StatusID
上的索引或在a
上构建哈希表:
SELECT *
FROM b
JOIN a
ON b.ID = a.StatusID
OPTION (FORCE ORDER)
PostgreSQL的家伙,对不起。您的TODO list说:
优化提示(不需要)
优化程序提示用于解决优化程序中的问题。我们宁愿报告和修复问题。
至于比较中的顺序,在任何RDBMS
,AFAIK中无关紧要。
虽然我个人总是试图估算要搜索的列,并将此列放在左侧(因为它看起来像lvalue
)。
有关详细信息,请参阅this answer。
答案 1 :(得分:9)
不,不。
我做的(为了便于阅读)是你的第二个例子。
答案 2 :(得分:5)
没有。数据库应该根据整个标准确定最佳执行计划,而不是通过按顺序查看每个项目来创建它。您可以通过请求两个查询的执行计划来确认这一点,您将看到它们是相同的(您会发现即使是最大不同的查询,只要它们最终指定相同的逻辑,通常会被编译到相同的执行计划中)。
答案 3 :(得分:1)
不,没有。在一天结束时,您只是在评估是否a = b。
并且作为平等状态的对称属性:
因此,无论您检查(12)*=12
还是12=(12)*
,都会在逻辑上没有区别。
如果值相等,则加入,否则不加入。无论你是在第一个例子还是第二个例子中指定它,都没有区别。
答案 4 :(得分:1)
SqlServer包含一个比这更复杂的情况的优化。
如果您有多个标准,那么通常会对延迟评估(但我需要对边缘情况进行一些研究,如果有的话。)
为了便于阅读,我通常更喜欢
SELECT Name, Status FROM a
JOIN b
ON a.StatusID = b.ID
我认为以变量的相同顺序引用变量更有意义,但它确实是个人品味的东西。
答案 5 :(得分:1)
我不会使用你的第二个例子的唯一原因:
select a.Name, b.Status
from a
inner join b
on b.ID = a.StatusID
您的用户更有可能回来说'即使他们没有状态记录,我能看到所有a.name'吗?'而不是“我能看到所有的b.status,即使他们没有名字记录吗?”,所以为了提前计划这个例子,我会使用On a.StatusID = b.ID
来预期LEFT Outer Join。这假设您可以拥有没有'b'的表'a'记录。
更正:它不会改变结果。
这可能是一个有争议的问题,因为用户从不想改变他们的要求。
答案 6 :(得分:1)
正如许多人所说:顺序对结果或表现没有影响。
我想指出的是, LINQ to SQL只允许第一种情况!
例如,以下示例效果很好,......
var result = from a in db.a
join b in db.b on a.StatusID equals b.ID
select new { Name = a.Name, Status = b.Status }
...虽然这会在Visual Studio中引发错误:
var result = from a in db.a
join b in db.b on b.ID equals a.StatusID
select new { Name = a.Name, Status = b.Status }
会抛出这些编译错误:
虽然与标准SQL编码无关,但在适应其中任何一个时,可能需要考虑这一点。
答案 7 :(得分:0)
select a.*, b.*
from tableA a
inner join tableB b
on a.name=b.name
and a.type=b.type
每个表引用都在一个单独的行上,每个连接条件都在一个单独的行上。标签有助于保持属于什么直接。
我喜欢做的另一件事是让我的on语句中的条件与表格的顺序相同。因此,如果a是第一个然后是b,则a将位于左侧,b位于右侧。
答案 8 :(得分:0)
错误:ON子句引用右侧的表(php sqlite 3.2)
替换
LEFT JOIN itm08 i8 ON i8.id= **cdd01.idcmdds** and i8.itm like '%ormit%'
LEFT JOIN **comodidades cdd01** ON cdd01.id_registro = u.id_registro
对于此
LEFT JOIN **comodidades cdd01** ON cdd01.id_registro = u.id_registro
LEFT JOIN itm08 i8 ON i8.id= **cdd01.idcmdds** and i8.itm like '%ormit%'