哪些选择语句“更好”,为什么?

时间:2009-06-02 16:42:10

标签: sql sql-server

我有2个人和角色。 我必须以角色为基础的所有人。

select person.* from person inner join role on
person.roleid = role.id Where role.id = @Roleid

select person.* from person inner join role on
person.roleid = role.id AND role.id = @Roleid

上述两种解决方案中哪一项更好,为什么?

10 个答案:

答案 0 :(得分:13)

第一个更好,因为它在逻辑上是连贯的。范围条件与连接无关,因此将其作为连接的一部分是一个kludge,在这种情况下是无用的。

答案 1 :(得分:9)

关系代数没有区别。来自这里和内部联接的标准是可以互换的。我根据可读性和情况使用两者。

在这种特殊情况下,您还可以使用:

select person.* from person WHERE person.roleid = @Roleid

唯一的区别是它不需要在角色表中存在一行(但我假设你具有参照完整性)并且如果roleid不是唯一的,它将不会返回多行(它几乎肯定是在我可以预见的大多数场景。)

答案 2 :(得分:8)

最好的办法是尝试这些查询并通过MS Sql的执行计划运行它们。我做了这个,结果看起来像这样:

Execution plan showing identical performance of queries http://img223.imageshack.us/img223/6491/querycompare.png

正如您所看到的,性能是相同的(已授予,在您的数据库上运行它可能会产生不同的结果。)因此,最佳查询是一个遵循用于编写查询的一致约定。

答案 3 :(得分:2)

SQL Server应该以相同的方式评估这些查询。就个人而言,我会使用AND。我喜欢在连接中保留连接表的所有条件,以便它们可以一起使用,并且很容易找到。

答案 4 :(得分:2)

两个查询都是相同的。在查询处理期间,SQL Server在应用连接条件过滤器后立即应用WHERE过滤器,因此您最终将以相同的方式过滤。

答案 5 :(得分:2)

我更喜欢#1,我相信它更好地表达了声明的意图。您正在加入基于roleid&的两个表。 role.id以及您基于@Roleid进行过滤

SELECT person.* 
FROM person INNER JOIN role ON person.roleid = role.id 
Where role.id = @Roleid

答案 6 :(得分:0)

Sqlserver可能有一个等同于“解释计划”的声明,Oracle,PostgreSQL和MySQL都支持这种或那种形式。它可以非常有用地告诉您查询解析器和优化器将如何处理您的查询。

答案 7 :(得分:0)

我会选择第一个,但记得在测试代码时你应该明确选择每个表,而不是做select *

答案 8 :(得分:0)

由于您没有从role获取列,因此最好不要将其包含在FROM子句中。使用此:

SELECT *
FROM   person
WHERE  person.roleid IN (SELECT id FROM role WHERE id = @Roleid)

这样,优化器只能看到FROM子句中的一个表,并且可以快速找出结果集的基数(即结果集中的行数< =表中的行数{ {1}})。

当您使用person抛出两个表时,优化器必须查看JOIN子句以确定这些表是否是等连接的,以及连接列上是否存在唯一索引。如果ON子句中的谓词很复杂(多个AND和OR)或者只是错误(有时非常错误),优化器可能会选择次优连接策略。

显然,这个特定的示例非常有用,因为您可以直接按ON过滤persons(无加入或子查询),但如果您必须过滤其他列,则上述注意事项有效roleid = @Roleid(例如@Rolename)。

答案 9 :(得分:-4)

使用此查询会产生任何性能影响吗?

SELECT person.* FROM person,role WHERE person.roleid=role.id AND role.id=@RoleID