2008-09-22 127 views
11

我有两个包含任务和注释的表格,并且想要检索每个任务的相关注释数量的任务列表。这两个查询做的工作:Transact-SQL - 子查询或左连接?

select t.TaskId, 
     (select count(n.TaskNoteId) from TaskNote n where n.TaskId = t.TaskId) 'Notes' 
from Task t 

-- or 
select t.TaskId, 
     count(n.TaskNoteId) 'Notes' 
from Task t 
left join 
     TaskNote n 
on  t.TaskId = n.TaskId 
group by t.TaskId

他们之间有一个区别,我应该使用了另一种,或者是他们做同样的工作的只有两个方法呢?谢谢。

回答

12

在小数据集他们洗,当涉及到性能。当索引时,LOJ会好一点。

我对大数据集是一个内部联接中(内部联接将工作太)将通过一个非常大的因素(对不起,没有数字)跑赢子查询。

+0

同上内部连接 ​​- 我已经看到这对大集合有很大的影响(假设这是你想要的正确行为,并且你可能需要使用ISNULL()或类似的函数) – 2008-09-22 22:31:01

0

您可以使用任意一种,并且它们在语义上是相同的。一般来说,经验法则是使用哪种形式更容易阅读,除非性能是一个问题。

如果性能是一个问题,然后使用其他形式的重写查询实验。有时优化器将使用一个索引而不是另一个索引。

1

对此没有明确的答案。您应该查看SQL计划。就关系代数而言,它们本质上是等价的。

6

在大多数情况下,优化器会将它们视为相同。

我倾向于选择第二个,因为它有较少的嵌套,这使得它更易于阅读和更易于维护。出于同样的原因,我开始使用SQL Server的公用表表达式来减少嵌套。

此外,第二语法是更灵活的,如果有进一步的聚集体,其可能会在将来,除了被加入到COUNT,像MIN(some_scalar),MAX(),AVG()等等

2

如果您正在使用SQL Server Management Studio,可以将两个版本都输入到查询编辑器中,然后右键单击并选择显示预计执行计划。它会给你两个相对于该批次的百分比成本。如果他们预计会采取同样的时间,他们都会显示为50% - 在这种情况下,由于其他原因(更易于阅读,更容易维护,更符合您的编码标准等)选择您喜欢的。否则,您可以选择相对于该批次具有较低百分比成本的那个。

您可以用同样的方法来看待改变任何查询,通过比较两个版本的做同样的事情来提高性能。

当然,因为它是相对于该批次成本,这并不意味着,要么查询一样快,因为它可能是 - 它只是告诉你他们如何互相比较,而不是一些名义上的最佳查询得到相同的结果。

5

因为它是被用于在外部查询的每一行执行的子查询速度会变慢。连接一次会更快。我相信查询优化器不会重写这个查询计划,因为它无法识别等价。

通常情况下,您会为这种计数做一个连接和分组。如果他们必须在没有参与另一个连接的表上执行一些分组或更复杂的谓词,则显示的排序的相关子查询主要是感兴趣的。

1

我在任何可能的地方避免子查询。联合通常会更有效率。