(注意:不是this question的副本,因为该问题有一个特定的查询。这更多来自一般的理论观点。)
我正在学习大学数据库,并且我已经了解到SQL数据库为了执行查询,首先将其转换为relational algebra,以便形成如何执行它的计划。关系代数使得表示非相关SQL子查询变得非常容易,然后我们可以根据需要将它们组合成连接或设置操作。例如,我们可以很容易地表达
SELECT y FROM Table WHERE y NOT IN (SELECT x FROM AnotherTable);
作为两个查询之间的集合差异。
然而,据我所知,关系代数没有提供表达相关子查询的SQL概念的机制,也没有提供从父查询中捕获列的查询,因此必须多次执行,例如本例下面:
SELECT employee_number, name
FROM employees AS emp
WHERE salary > (
SELECT AVG(salary)
FROM employees
WHERE department = emp.department);
(在此示例中,外部WHERE
子句中的子查询与员工的部门相关联,这意味着必须为每个员工运行一次子查询,以便按部门筛选结果。)
与许多其他相关子查询一样,可以通过使用连接和单个聚合查询来解相关此子查询,这将允许查询在RA中完全可表达并且还使子查询仅运行一次:
SELECT emp.employee_number, emp.name
FROM employees AS emp
JOIN (
SELECT department AS department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department) AS salaries
ON emp.department = salaries.department
WHERE emp.salary > salaries.avg_salary;
是否有可能将所有相关子查询表示为去相关子查询,以便将它们表示为关系代数,或者是否存在一些必须表达的相关子查询?换句话说,SQL关联只是一个便利功能,它不会为SQL的表达能力添加任何东西,或者RA只是一个实现指南,因为这个功能,SQL更具表现力吗?
如果是前者,这是什么证明/算法?如果是后者,是否有一种普遍接受的RA形式直接表达相关性?
答案 0 :(得分:1)
我想在这里指出,你可能会误解到一个子查询到底是什么“相关”。
根据我的理解,如果子查询仅包含来自包含(/外部)查询的列,则子查询是“相关的”。您的SELECT AVG(...)查询不符合该描述。它就是所谓的标量子查询。因为它只会从某个表中计算标量值。它也可以“独立”。
至于实际问题,确定此特定查询的RA表示法的任何困难都是由于查询涉及聚合这一事实,并且RA表示法通常不支持表示此类操作。如果他们这样做了,原始表格与您的SELECT AVG(...)以及JOIN上所需的RESTRICT的JOIN将解决您的问题。
答案 1 :(得分:1)
首先,可以在关系代数和聚合中表达相关子查询(->依赖联接)。
您可能对此感兴趣:http://www.btw-2015.de/res/proceedings/Hauptband/Wiss/Neumann-Unnesting_Arbitrary_Querie.pdf
我还没有阅读整篇论文,但是我和Neumann教授一起上了课。他声称您可以取消关联任意查询。 但是我相信有一些限制。
select *
from T1
where T1.a = (select T2.a from T2 where T2.b = T1.b)
原则上,解相关该查询将很容易,在查看了查询计划后,我相信他们主持的数据库系统能够做到这一点(https://hyper-db.de/interface.html)。我认为您无法在SQL中表达这一点,因为如果子查询未返回标量(https://blogs.msdn.microsoft.com/craigfr/2006/09/27/scalar-subqueries/),则会在此出现运行时错误。