EMP*_*EMP 2 sql sqlite specifications group-by
我有一个名为"message"的简单SQLite表:
sequence INTEGER PRIMARY KEY
type TEXT
content TEXT
Run Code Online (Sandbox Code Playgroud)
我想获取每种类型的最后一条消息的内容(由其序列决定).令我惊讶的是,以下简单查询有效:
SELECT MAX(sequence), type, content
FROM message
GROUP BY type
Run Code Online (Sandbox Code Playgroud)
很惊讶,因为我知道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
Run Code Online (Sandbox Code Playgroud)
我的问题是:在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;
Run Code Online (Sandbox Code Playgroud)
上面的例子可以在SQLite中使用,并产生一个明确的结果,因为p.any_column
每组不可能有多个值.但是,此查询严格违反SQL标准,大多数品牌的RDBMS都会引发错误.
但是,编写一个产生模糊结果的查询太容易了.为每个组命名一个具有多个值的列时,无法控制结果集中返回的值.
在实践中,MySQL返回第一行中相对于物理存储的值,SQLite返回最后一行的值.但它完全依赖于实现而且不可靠.如果任一软件的下一个版本更改其内部,则升级后可能会得到不同的查询结果.所以最好不要依赖这种行为.
关于你的例子,哪里content
应该"直观地"得到sequence
MAX 行的值.但这真的很直观吗?考虑以下其他情况:
SELECT MAX(sequence), MIN(sequence), type, content
FROM message
GROUP BY type
Run Code Online (Sandbox Code Playgroud)
那么哪一行现在提供的价值content
?哪一行sequence
是MAX,sequence
哪一行是MIN?
如果您使用非唯一列(例如date
),并且有多个行具有相同的MAX值date
,但是不同的值,该content
怎么办?
SELECT MAX(date), type, content
FROM message
GROUP BY type
Run Code Online (Sandbox Code Playgroud)
什么样的其他聚合函数AVG()
或SUM()
?可能是聚合的值对应于表中没有单独的行.那么现在哪一行应该提供的价值content
?
SELECT AVG(sequence), type, content
FROM message
GROUP BY type
Run Code Online (Sandbox Code Playgroud)