企业可以使用三个表来跟踪其员工的缺勤天数。它来自 Joe Celko 的 SQL 谜题集。读者的任务是编写一条 DELETE 语句,以删除累计缺勤 40 天或以上的员工。为此,我们使用子查询。作者提出的一个是这样的:
DELETE FROM Personnel
WHERE emp_id = (SELECT A1.emp_id
FROM Absenteeism AS A1
WHERE A1.emp_id = Personnel.emp_id
GROUP BY A1.emp_id
HAVING SUM(severity_points) >= 40);
我的问题是,为什么要选择相关的?运行像下面这样的东西不是更有效率吗?
DELETE FROM Personnel
WHERE emp_id =
(SELECT emp_id FROM Absenteeism
GROUP BY emp_id
HAVING SUM(severity_points) >= 40)
谢谢!
如果子查询返回多行(很可能会),您建议的非相关版本将失败。你应该使用
IN
而不是=
在这里。Celko 关联的目的是确保从子查询中只返回零行或一行(因为它在 emp_id 上匹配和分组)。另外,不要忘记在子查询中为表设置别名并显式引用别名。由于两个表(Personnel 和 Absenteeism)都有一个 emp_id 列,您希望非常清楚您指的是哪个表。
这更像是可读性的“最佳实践”,但也可以防止查询中的逻辑问题和错误。例如,此查询将删除表中的每一行:
当然,这可能看起来像一个人为的例子,但它确实发生了:sql server 2008 management studio not checking the syntax of my query
所以这是更新的查询:
鉴于这些变化:你是对的,在这种情况下,相关性并不是绝对必要的。
从逻辑上讲,相关版本似乎更有效,尤其是当 Absenteeism 表中有很多行在 Personnel 表中没有匹配项时(因为无界子查询可能会读取更多数据)。
但是必须进行测试才能确定。查询优化器可以接受您编写的声明式查询并用它做很多不同的事情。