为啥此相关子查询在 Oracle 和 SQL Server 中的工作方式不同
Posted
技术标签:
【中文标题】为啥此相关子查询在 Oracle 和 SQL Server 中的工作方式不同【英文标题】:Why this correlated subquery works differently in Oracle and SQL Server为什么此相关子查询在 Oracle 和 SQL Server 中的工作方式不同 【发布时间】:2019-12-07 23:41:14 【问题描述】:我有表 EMPLOYEES,其中包含employee_id、department_id、salary 列(标准 HR 模式)。
为什么要查询:
SELECT
employee_id,
department_id,
salary,
(
select min(EMPLOYEES.salary)
from HR.EMPLOYEES E
where department_id = EMPLOYEES.department_id
)
from HR.EMPLOYEES;
在 Oracle 中执行但在 SQL Server 中返回错误?
【问题讨论】:
您能否通过“在 Oracle 中工作但在 SQL Server 中不工作”的意思给我们一个提示? 我的错误:“在 Oracle 中执行,但在 SQL Server 中返回错误”更加精确。但我已经收到了答案。 好的,一个更具描述性的帖子将有助于包含实际的错误消息。这很容易,但将来问题可能不会那么明显。欢迎来到 SO! 【参考方案1】:SQL Server 不允许在相关子查询的聚合中引用外部查询。这通常很好,因为这样的结构通常不是很有用。我很确定错误消息是这样说的。
我认为这是您真正想要的查询:
select e.employee_id, e.department_id, e.salary,
(select min(e2.salary)
from HR.EMPLOYEES E2
where e2.department_id = e.department_id
)
from HR.EMPLOYEES e;
我会建议您限定所有列引用,尤其是在相关子查询中。
您的版本将只返回外部查询中每个员工的薪水。您不需要相关的子查询来执行此操作。
【讨论】:
“SQL Server 不允许在相关子查询的聚合中引用外部查询。”你回答了我的问题。错误消息正是如此。当然,我不需要相关的子查询来做到这一点,我只是很惊讶为什么 Oracle 和 SQL Server 之间存在差异......【参考方案2】:您需要在子查询中限定department_id
列,否则它所引用的表是不明确的。某些 RDBMS 可能允许使用您的语法,但我不确定这是否会产生正确的结果。
为子查询返回的值提供别名也是一个好主意。
因此:
select
employee_id,
department_id,
salary,
(
select min(e1.salary)
from hr.employees e1
where e1.department_id = e.department_id
) min_department_salary
from hr.employees e;
另外,请注意,您可以通过使用窗口函数(Oracle 和 SQLServer 已经支持很长时间)在不使用子查询的情况下获得相同的结果:
select
employee_id,
department_id,
salary,
min(salary) over(partition by department_id) min_department_salary
from hr.employees e;
【讨论】:
以上是关于为啥此相关子查询在 Oracle 和 SQL Server 中的工作方式不同的主要内容,如果未能解决你的问题,请参考以下文章
将 TOP 1 相关子查询从 SQL Server 翻译到 Oracle