【问题标题】:Is it possible to decorrelate all correlated SQL subqueries?是否可以去关联所有相关的 SQL 子查询?
【发布时间】:2018-07-19 10:12:54
【问题描述】:

(注意:不是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 形式?

【问题讨论】:

    标签: sql theory relational-algebra


    【解决方案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/),则会出现运行时错误。

    【讨论】:

    • 很容易将标量子查询的相等性映射到例如 IN 然后是 JOIN。另外:在他关于谓词逻辑风格的非代数查询语言的第一篇论文中,Codd 展示了如何将此类表达式映射到关系代数。由于(合适的强)关系代数可以表达数据库状态的任何(合适的强)函数,SQL 可以映射到它。
    【解决方案2】:

    我想在这里指出,您可能对子查询何时“相关”存在误解。

    在我的理解中,子查询是“相关的”,当且仅当它引用来自包含(/外部)查询的列。您的 SELECT AVG(...) 查询不符合该描述。这就是所谓的标量子查询。因为它只是从某个表中计算一个标量值。而且它还可以“自立”。

    至于实际问题,确定此特定查询的 RA 表示法的任何困难是由于查询涉及聚合,并且 RA 表示法通常不支持表示这样的操作。如果他们这样做了,则将原始表与您的 SELECT AVG(...) 以及该 JOIN 所需的 RESTRICT 相结合,将解决您的问题。

    【讨论】:

    • 感谢您的澄清。我会在这里注意到,我确实使用 JOIN 在问题中成功地对 SELECT AVG() 查询进行了去关联。我要问的是能够将 任何 相关查询表示为去相关 RA 查询的一般情况,或者 RA 是否直接支持相关概念。
    • @TheHansinator 关系代数没有“相关”的概念,因为它们没有绑定/量化/逻辑变量。然而,适当重新排列的表达式对应于代数表达式。有关这方面的示例,请参阅 Codd 的 ALPHA 论文。这在 SQL 中演示很痛苦,因为它的语法和语义很糟糕。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-07
    相关资源
    最近更新 更多