SQLite 中 WHERE 子句中的聚合函数
Posted
技术标签:
【中文标题】SQLite 中 WHERE 子句中的聚合函数【英文标题】:Aggregate functions in WHERE clause in SQLite 【发布时间】:2010-09-28 06:42:11 【问题描述】:简单地说,我有一个表格,其中包含时间戳列。我想获得具有最新(即最大值)时间戳的行。目前我正在这样做:
SELECT * FROM table ORDER BY timestamp DESC LIMIT 1
但我更愿意做这样的事情:
SELECT * FROM table WHERE timestamp=max(timestamp)
但是,SQLite 拒绝了这个查询:
SQL error: misuse of aggregate function max()
documentation 确认了这种行为(页面底部):
聚合函数只能在 SELECT 语句中使用。
我的问题是:是否可以编写查询以获取具有最大时间戳的行,而无需对选择进行排序并将返回的行数限制为 1?这似乎应该是可能的,但我想我的 SQL-fu 还达不到标准。
【问题讨论】:
【参考方案1】:给猫剥皮的方法有很多种。
如果您有一个具有自动增量功能的标识列,如果您按 ID 返回最后一条记录,由于该列的索引,会产生更快的查询,除非您当然希望在时间戳列。
SELECT * FROM TABLE ORDER BY ID DESC LIMIT 1
【讨论】:
【参考方案2】:你可以简单地做
SELECT *, max(timestamp) FROM table
编辑: 由于聚合函数不能像这样使用,所以会出错。我猜SquareCog 的建议是最好的做法
SELECT * FROM table WHERE timestamp = (select max(timestamp) from table)
【讨论】:
【参考方案3】:我想我在过去一周已经回答了 5 次这个问题,但是我太累了,现在找不到其中一个的链接,所以又来了……
SELECT
*
FROM
table T1
LEFT OUTER JOIN table T2 ON
T2.timestamp > T1.timestamp
WHERE
T2.timestamp IS NULL
您基本上是在寻找比它晚的没有其他行匹配的行。
注意:正如 cmets 中所指出的,这种方法在这种情况下表现不佳。在您希望每个客户的最后一行(例如)的情况下,它通常会更好地工作(至少对于 SQL Server)。
【讨论】:
这可以工作,但执行连接不会导致一些性能损失吗? 这行得通,但效率低下真是太棒了。假设原始表中有 10 行,这将产生(并丢弃)55 行。对于 100 行,您生成的集合大小为 5,050。它长得真快。最好只进行两次扫描。 哦,当您有两行具有相同的最大时间戳时,这不起作用。 @Dmitriy - 如果两行具有相同的最大时间戳,您自己的解决方案会给出完全相同的结果。至于效率,在这个简单的示例中,使用子查询效果更好,但在您希望最后一行按另一列分组的情况下效果不佳。 汤姆,你是对的,我撤回了关于你的解决方案不起作用的评论。但我认为这是非常低效的。至于按另一列分组——嗯?只需输入“按 x 分组”即可。也许我不明白这个场景?一般来说,作为一种哲学,我尽量避免接近笛卡尔连接。【参考方案4】:SELECT * from foo where timestamp = (select max(timestamp) from foo)
或者,如果 SQLite 坚持将子选择视为集合,
SELECT * from foo where timestamp in (select max(timestamp) from foo)
【讨论】:
效果很好,谢谢。我知道它必须是简单的。 只是好奇,子查询会导致 sqlite 处理表两次,还是优化掉了? 它确实会处理表格两次——一次是为了找到最大值,另一次是为了找到匹配项。我不确定您是否可以从 SQL 中获得一次性算法。以上是关于SQLite 中 WHERE 子句中的聚合函数的主要内容,如果未能解决你的问题,请参考以下文章