今日在某数据库官方文档中看到了子链接的概念,不是很理解。就进行了搜索和查询,结果不成想扯出了几个没跟查询相关的,自己不是很熟悉的概念,贴在这里供自己翻查。
子链接&子查询
在SQL中,"子链接"通常是指"子查询"(subquery),这是一种将一个查询语句嵌套在另一个查询语句中的技术。子查询可以出现在SELECT, INSERT, UPDATE, DELETE语句或甚至在另一个子查询中。它们允许你使用一个查询的结果作为另一个查询的条件。
子查询可以根据其位置和功能分为多种类型:
-
独立子查询:这种类型的子查询不依赖于外部查询,并且只执行一次,然后将其结果提供给外部查询。
-
相关子查询:与独立子查询不同,相关子查询依赖于外部查询的数据。这意味着对于外部查询中的每一行,子查询都可能需要重新执行,以确定是否满足特定的条件。这通常会导致性能问题,特别是在大数据集上。
-
标量子查询:返回单个值的子查询,这个值可以用于比较、赋值等操作。
-
行子查询:返回一行数据的子查询,可以用于比较整行。
-
表子查询:也称为内联视图,它返回一个结果集,可以像表一样被引用。
子查询在编写复杂的SQL语句时非常有用,它们可以使逻辑更加清晰,但有时也可能导致性能不佳。在某些情况下,可以通过重写为连接(JOIN)或其他方式来优化包含子查询的SQL语句。
子查询为什么又叫子链接
在SQL语境中,"子查询"(subquery)有时也被称作"子链接"(sublink),尤其是在某些数据库系统或文献中。这个术语的使用可能源于子查询与外部查询之间的逻辑关联方式。当一个子查询被用作外部查询的一部分时,它就像一个“链接”一样,将两个查询连接在一起。
具体来说,当一个子查询作为外部查询中的条件表达式出现时,它可以被视为对外部查询结果集中的每一行进行某种形式的过滤或计算。在这种情况下,子查询就好像是为外部查询提供了一个动态的、基于数据的“链接”,来帮助决定哪些行应该被包含在最终的结果集中。
例如,在以下SQL语句中:
SELECT * FROM employees
WHERE department_id IN (SELECT department_id FROM departments WHERE location = 'New York');
这里的IN (SELECT department_id FROM departments WHERE location = 'New York')
就是一个子查询,它作为WHERE
子句的一部分,用于过滤employees
表中的记录。你可以认为这个子查询是外部查询和departments
表之间的一个“链接”。
不过,“子链接”这个术语并不是非常常见,并且不同的数据库文档可能会使用不同的术语来描述相同的概念。
主查询&外部查询
在SQL中,当一个查询包含另一个查询时,我们通常将外面的查询称为“外部查询”(outer query),而里面的查询则被称为“子查询”(subquery)。外部查询是主查询,它可能使用子查询的结果来作为条件、数据源或者用于其他目的。
举个例子,下面是一个简单的外部查询和子查询的例子:
SELECT *
FROM orders o
WHERE o.customer_id IN (SELECT customer_id FROM customers WHERE country = 'USA');
在这个例子中:
SELECT * FROM orders o WHERE o.customer_id IN (...)
是外部查询。它从orders
表中选择所有记录。(SELECT customer_id FROM customers WHERE country = 'USA')
是子查询。它返回的是居住在美国的所有客户的customer_id
。
外部查询使用子查询的结果来过滤出那些客户ID在子查询结果集中的订单记录。也就是说,外部查询只选择了那些顾客来自美国的订单。
子查询可以出现在外部查询的不同位置,例如:
- 在
WHERE
子句中,用作过滤条件。 - 在
FROM
子句中,作为一个临时的结果集(也称为内联视图或派生表)。 - 在
SELECT
子句中,用于计算列值。 - 在
HAVING
子句中,用于聚合后的过滤。
外部查询与子查询之间的这种关系使得SQL能够表达复杂的逻辑,并允许数据库引擎执行多层次的数据处理。理解这两者的关系对于编写高效的SQL查询非常重要。
子查询提升是指啥
子查询提升(Subquery Unnesting 或 Subquery Flattening)是一种数据库优化技术,它指的是将嵌套的子查询转换为更简单的形式,通常是通过将其与外部查询合并,从而提高查询性能。这种优化可以减少查询执行所需的步骤,降低资源消耗,并且可能提高查询的速度。
在某些情况下,子查询可能会导致数据库引擎执行多次相同的查询,特别是在相关子查询中,对于外部查询的每一行都可能需要重新执行一次子查询。这会大大增加处理时间和计算成本。子查询提升的目的就是消除这些重复的工作,通过重写查询来避免不必要的重复操作。
例如,考虑以下带有相关子查询的SQL语句:
SELECT e.*
FROM employees e
WHERE e.salary > (SELECT AVG(salary) FROM employees WHERE department_id = e.department_id);
在这个例子中,对于employees
表中的每一行,都需要计算该部门的平均工资。如果这个表很大,那么这个查询可能会非常慢。
通过子查询提升,数据库优化器可能会尝试将上述查询改写为使用连接(JOIN)的形式,比如:
SELECT e1.*
FROM employees e1
JOIN (
SELECT department_id, AVG(salary) as avg_salary
FROM employees
GROUP BY department_id
) e2
ON e1.department_id = e2.department_id
WHERE e1.salary > e2.avg_salary;
这样做的好处是只需要计算每个部门的平均工资一次,然后将结果与employees
表进行连接,从而减少了计算量和提高了效率。
需要注意的是,子查询提升是由数据库优化器自动完成的,不需要用户手动干预。但了解这一点可以帮助你写出更易于被优化的SQL代码。不同的数据库系统有不同的优化策略和能力,因此实际的效果也会有所差异。