SQLite - 计数如何在没有 GROUP BY 的情况下工作?

Joh*_*ohn 7 sqlite aggregate

有一个像这样的表:

first_name    last_name
------------------------
jack          frost
john          wayne
betty         white
null          jackson
Run Code Online (Sandbox Code Playgroud)

这个查询:

first_name    last_name
------------------------
jack          frost
john          wayne
betty         white
null          jackson
Run Code Online (Sandbox Code Playgroud)

MySQL 和 Postgres 甚至不会运行它。他们以某种方式知道这需要 GROUP BY。

SQLite 生成单行结果:jack 3

MySQL 和 Postgres 如何知道这需要 GROUP BY?为什么还需要 GROUP BY?

为什么 SQLite 的结果是一行?我本来期望输出是这样的:

jack 3
john 3
betty 3
null 3
Run Code Online (Sandbox Code Playgroud)

Len*_*art 13

SQLite 不遵守这方面的标准。请参阅https://www.sqlite.org/quirks.html#aggregate_queries_can_contain_non_aggregate_result_columns_that_are_not_in_the_group_by_clause

SQLite 将聚合之外的first_name 称为“裸”列,请参见第2.5 节。在https://www.sqlite.org/lang_select.html#resultset

您可以将您的查询想象为:

SELECT first_name, COUNT(first_name)
FROM tbl
GROUP BY () -- empty set
Run Code Online (Sandbox Code Playgroud)

这意味着您的聚合函数适用于结果集中的所有行,即

jack, count({jack, john, betty, null})
john, count({jack, john, betty, null})
betty,count({jack, john, betty, null})
null, count({jack, john, betty, null})
Run Code Online (Sandbox Code Playgroud)

null没有考虑到count,所以我们最终得到:

jack, 3
john, 3
betty,3
null, 3
Run Code Online (Sandbox Code Playgroud)

由于聚合函数(在本例中为 COUNT)应该对每个组进行聚合,因此我们应该在结果中得到 1 行(我们只有 1 个组,即空集的组)。因此,随机选取一行,例如

john, 3
Run Code Online (Sandbox Code Playgroud)

有人可能会问为什么不进一步偏离标准并允许 4 行结果呢?这只是一个猜测,但我怀疑其目的是最终修复第一个偏差(可能通过类似于 MySQL 的设置)。因此,我怀疑他们无意火上浇油,而他们最终会试图解决根本原因。

如果您的目的是计算每个名字的所有行(不包括空值),您可以使用窗口函数:

select first_name, count(first_name) over () from tbl;
Run Code Online (Sandbox Code Playgroud)

小提琴

  • COUNT 每组返回 1 行。如果没有分组依据(或按空集分组),则仅返回一行。 (3认同)

Rol*_*DBA 5

这不是COUNT()函数应该使用的方式。

根据 SQLite 文档,COUNT()是一个聚合函数,就像 MIN()、MAX()、SUM()、AVERAGE() 和 GROUP_CONCAT() 一样

如果没有GROUP BY子句,COUNT()将聚合整个表,将其视为一个组。

最新版本的 MySQL 和 PostgreSQL 不允许这样做。非常旧版本的 MySQL 会。

在你的例子中,SQLite 显然做了的是

  • 给你它看到的第一个非空值first_name
  • 对first_name的所有非空值执行COUNT()聚合