ITPub博客

首页 > 数据库 > 数据库开发技术 > 一个神奇的SQL聚合查询案例

一个神奇的SQL聚合查询案例

原创 数据库开发技术 作者:BUAA_dxy 时间:2024-01-12 21:00:00 0 删除 编辑

今天给大家分享一个 SQL 案例,假如存在以下两个表:

CREATE TABLE t1 (val1 INT);
INSERT INTO t1 VALUES (1), (2), (3);

CREATE TABLE t2 (val2 INT);
INSERT INTO t2 VALUES (10), (20), (30);

每个表包含 3 条数据。请问,以下查询返回结果是什么?

SELECT (SELECT sum(val1) 
FROM t2
LIMIT 1) res
FROM t1;

不同数据库对于上面的查询实现并不一致,大体可以分为两种。

实现方法一

对于 MySQL、SQL Server、PostgreSQL 以及 SQLite 而言,查询结果如下:

res|
---+
6|

它们的实现逻辑如下:

SELECT (SELECT sum_a
FROM t2
LIMIT 1
)
FROM (SELECT sum(val1) AS sum_a
FROM t1
) tmp;

也就是说,子查询中的 sum(val1) 是外部查询的结果。先执行以下外部查询:

SELECT sum(val1) AS sum_val1
FROM t1;

sum_val1|
--------+
6|

然后执行以下子查询:

SELECT 6 res
FROM t2
LIMIT 1;

所以查询最终返回了一个 6。

如果我们把子查询中的 LIMIT 去掉,将会返回以下错误:

SQL 错误 [1242] [21000]: Subquery returns more than 1 row

这也说明了 sum 函数是在外部查询中执行,因为以下聚合函数不会返回多条数据:

SELECT sum(expression) 
FROM t2

实现方法二

对于另外一些数据库而言,例如 Oracle,查询结果如下:

SELECT (SELECT sum(val1) 
FROM t2
FETCH FIRST 1 ROWS ONLY) res
FROM t1;

RES|
---+
3|
6|
9|

它的实现逻辑是先执行外部查询 t1,返回 3 条数据(1,2,3)。然后将结果传递给子查询,计算 sum,最终返回了 3 条数据。

查询中的 FETCH FIRST 1 ROWS ONLY 可以省略,因为聚合查询只会返回一条数据。

另外一个查询语句

我们再考虑一种情况,以下查询语句应该返回什么结果:

SELECT (SELECT sum(val1+val2) 
FROM t2
LIMIT 1) res
FROM t1;

子查询中的 sum 函数同时使用了 t1 和 t2 的字段。

此时,MySQL、Oracle、PostgreSQL 以及 SQLite 都会返回 3 条记录:

res|
---+
63|
66|
69|

它们的实现逻辑回到了先执行外部查询 t1,返回 3 条数据(1,2,3)。然后将结果传递给子查询,计算 sum,最终返回了 3 条数据。此时,我们可以将语句中的 LIMIT 去掉,不会影响结果。

对于 SQL Server,以上语句回返回错误:

SQL 错误 [8124] [S0001]: 在包含外部引用的被聚合表达式中指定了多个列。如果被聚合的表达式包含外部引用,那么该外部引用就必须是该表达式中所引用的唯一的一列。

也就是说,它不支持聚合函数既引用内部表,又引用外部表。

原文作者:SQL编程思想;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论
《SQL编程思想》作者,专注于数据库领域知识的分享。

注册时间:2021-08-26

  • 博文量
    443
  • 访问量
    546927