我有两个包含Tasks和Notes的表,并希望检索一个任务列表,其中包含每个任务的关联注释数。这两个查询完成了这项工作:
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
它们之间是否存在差异,我应该使用其中一个,还是只是两种方式做同样的工作?感谢。
答案 0 :(得分:12)
在小型数据集上,它们在性能方面会被洗掉。索引时,LOJ稍好一些。
我在大型数据集上发现内部联接(内部联接也会起作用。)将超过子查询的一个非常大的因素(对不起,没有数字)。
答案 1 :(得分:6)
在大多数情况下,优化器会对它们进行相同的处理。
我倾向于选择第二种,因为它具有较少的嵌套,这使得它更易于阅读和更易于维护。我已经开始使用SQL Server的公用表表达式来减少嵌套,原因相同。
此外,如果还有其他聚合,除了COUNT之外可以在将来添加聚合,如MIN(some_scalar),MAX(),AVG()等,第二种语法会更灵活。
答案 2 :(得分:5)
子查询将在外部查询中的每一行执行时变慢。一旦完成,连接将更快。我相信查询优化器不会重写此查询计划,因为它无法识别等价。
通常你会为这种计数进行连接和分组。如果必须在未参与其他连接的表上执行某些分组或更复杂的谓词,则您显示的排序的相关子查询主要是有意义的。
答案 3 :(得分:2)
如果您使用的是SQL Server Management Studio,则可以在查询编辑器中输入两个版本,然后右键单击并选择“显示估计执行计划”。它将为您提供相对于批次的两个百分比成本。如果他们预计会花费相同的时间,他们都会显示为50% - 在这种情况下,选择您喜欢的其他原因(更容易阅读,更容易维护,更符合您的编码标准等)。否则,您可以选择相对于批次的百分比成本较低的那个。
您可以使用相同的技术来查看更改任何查询以通过比较执行相同操作的两个版本来提高性能。
当然,因为它是相对于批处理的成本,它并不意味着任何一个查询都尽可能快 - 它只是告诉你它们如何相互比较,而不是一些名义上的最佳查询得到相同的结果。
答案 4 :(得分:1)
对此没有明确的答案。您应该查看SQL计划。就关系代数而言,它们本质上是等价的。
答案 5 :(得分:1)
我尽可能避免使用子查询。加入通常会更有效率。
答案 6 :(得分:0)
您可以使用其中任何一个,它们在语义上是相同的。一般来说,经验法则是使用更容易阅读的形式,除非性能是一个问题。
如果性能有问题,请尝试使用其他表单重写查询。有时,优化器将使用一个表单的索引,而不是另一个表单。