在 SQLite GROUP BY 查询的 SELECT 列表中包含额外的列是否安全?

2024-06-25

我有一个简单的 SQLite 表,名为“message”:

sequence INTEGER PRIMARY KEY
type TEXT
content TEXT

我想获取每种类型的最后一条消息的内容(由其序列确定)。令我惊讶的是,以下简单查询有效:

SELECT MAX(sequence), type, content
FROM message
GROUP BY type

令人惊讶的是,因为我知道 MSSQL 或 Postgres 会拒绝在 SELECT 列表中包含不属于 GROUP BY 子句或聚合函数的列,并且我必须执行联接,如下所示:

SELECT m.sequence, m.type, m.content
FROM
(
    SELECT MAX(sequence) as sequence, type
    FROM message
    GROUP BY type
) g
JOIN message m
ON g.sequence = m.message_sequence

我的问题是:在 SQLite 中使用第一种更简单的查询形式安全吗?直观上讲,它选择与“MAX(序列)”值匹配的“内容”值,但文档似乎根本没有谈论这一点。当然,如果序列不唯一,那么结果将是不确定的。但是,如果序列是唯一的,就像我的情况一样,这是有保证的还是只是一个幸运的实现细节,可能会发生变化?


您可以“安全”地使用这些查询,也就是说,如果额外的列是功能依赖在您分组依据的列上:

SELECT c.parent_id, COUNT(*), p.any_column
FROM child_table c 
JOIN parent_table p USING (parent_id)
GROUP BY c.parent_id;

上面的例子可以在 SQLite 中运行,并产生明确的结果,因为没有办法p.any_column每组可以有多个值。然而,这个查询严格违反了SQL标准,大多数品牌的RDBMS都会报错。

不过,编写产生不明确结果的查询太容易了。当您命名的列每组有多个值时,您无法控制结果集中返回哪个值。

实际上,MySQL 返回的值来自first相对于物理存储的行,SQLite 从last排。但它完全依赖于实现并且不可靠。如果任一软件的下一个版本更改了其内部结构,则升级后您可能会得到不同的查询结果。所以最好不要依赖这种行为。


关于你的例子,其中content应该“直观地”具有来自行的值sequence是最大。但这真的是直观的吗?考虑以下其他情况:

SELECT MAX(sequence), MIN(sequence), type, content
FROM message
GROUP BY type

那么现在哪一行提供值content?所在行sequence是 MAX,或者是其中的行sequence is MIN?

如果您使用非唯一列(例如date),并且有多行具有相同的 MAX 值date,但不同的值content?

SELECT MAX(date), type, content
FROM message
GROUP BY type

其他聚合函数怎么样?AVG() or SUM()?聚合的值可能与表中没有单独的行相对应。现在哪一行应该提供值content?

SELECT AVG(sequence), type, content
FROM message
GROUP BY type
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 SQLite GROUP BY 查询的 SELECT 列表中包含额外的列是否安全? 的相关文章

随机推荐