GROUP BY查询中的非聚合列是否有保证

  • 本文关键字:是否 查询 BY GROUP sqlite group-by
  • 更新时间 :
  • 英文 :


假设我们在SQLite中有以下表和查询:

父abd
id val字母
1 3 10
2 3 10
3 0 10 c
4 5 20

SELECT/Simple SELECT Processing/旁注:聚合查询中的裸列中介绍了此行为

在查询中,未聚合且未包含在GROUP BY子句中的列idletter称为bare
因为您使用MAX()聚合函数,所以这两列的值:

。。。从输入行中获取值,该行还包含最小值或最大

但是,由于对于相同的parent:,可能存在超过1行的最大val

如果两个或多个输入行具有相同的最小或最大值

这意味着对于您的样本数据,不能保证对于parent = 10,您将在结果中获得具有id = 1的行
您可以得到具有id = 2的行,该行还包含最大val

假设在这种情况下,对于同一父级,可能存在超过1行具有最大val,您希望该行具有最小id,则可以使用窗口函数:

SELECT id, val, parent, letter
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY parent ORDER BY val DESC, id) rn
FROM tablename
)
WHERE rn = 1

或:

SELECT DISTINCT
FIRST_VALUE(id) OVER (PARTITION BY parent ORDER BY val DESC, id) id, 
MAX(val) OVER (PARTITION BY parent) val, 
parent, 
FIRST_VALUE(letter) OVER (PARTITION BY parent ORDER BY val DESC, id) letter
FROM tablename 

请参阅演示

来自官方文档

值得仔细阅读。粗体就是您要查找的内容。

聚合查询可以包含以下非聚合结果列不在GROUP BY子句中

在大多数SQL实现中,聚合查询的输出列可能仅引用GROUP BY中命名的聚合函数或列条款在聚合查询,因为每个输出行可能由两个或输入表中的多行。

SQLite不强制执行此限制。聚合查询可以是任意表达式,其中不包括在GROUP BY子句中找到。此功能有两个用途:

  1. 使用SQLite(但不是我们所知道的任何其他SQL实现(,如果聚合查询包含单个min((或max((函数,则输出中使用的列的值取自获得min((或max((值的行。如果两行或多行相同的min((或max((值,则将选择列值任意地从其中一行

。。。

现在,使用您的查询

SELECT id, MAX(val), parent, letter FROM table GROUP BY parent

您基本上有未聚合的idletter,它们不在GROUP BY中。

这意味着为它们返回的值是来自与MAX(val)匹配的行的值。

在你的情况下,有两个

id  val parent  letter
1   3   10      a
2   3   10      b

这意味着sqlite将任意(随机(返回第1行或第2行的值。所以不,你没有保证。

最新更新