在没有 ANY() 的情况下,哪个是最便宜的聚合函数
Posted
技术标签:
【中文标题】在没有 ANY() 的情况下,哪个是最便宜的聚合函数【英文标题】:Which is the least expensive aggregate function in the absence of ANY() 【发布时间】:2011-08-28 22:47:17 【问题描述】:如果 DBMS 没有 ANY() 聚合函数,我通常使用 MAX() 或 MIN()。
在 mysql 和 MS-SQL 中是否有更便宜的东西?
【问题讨论】:
为什么不存在 ANY() 聚合函数? 为什么会存在 ANY() 聚合函数?它的规格是什么?ANY()
是什么意思?它应该返回一个随机行吗?
any(expresion)
:返回组内的任何表达式值。为了在所有依赖列都相同或任何一个都很好的情况下具有良好的性能
ANSI-92 SQL contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt987654321@中没有任何聚合
【参考方案1】:
ANSI SQL-92 中没有 ANY 聚合
是匹配 SOME 和 ALL 的 ANY 限定符
TSQL - SOME | ANY why are they same with different names? (SO) ALL, ANY, and SOME: The Three Stooges(SQL Server 百科)MIN 和 MAX 是适当的聚合......完全不相关,不应该比较
编辑:
只有 MySQL 具有这种“ANY”聚合的模糊性:SQL Server、Sybase、Oracle、PostGres 没有。见Do all columns in a SELECT list have to appear in a GROUP BY clause
【讨论】:
我为“我的聚合”函数选择了错误的名称。但我的意思是如果存在的话,可以使用更便宜的 max() 或 min() 替代方法 太棒了! link SQL Server does have anANY
aggregate
@gbn - 我不知道重写查询是否有任何好处。由于不需要进行任何比较,因此可能会稍微减少 CPU 时间?
@Martin Smith:我会说这是处理上述情况的内部优化。直接用的话,会像mysql组一样乱七八糟【参考方案2】:
MySQL 不需要 ANY() 聚合。
如果我做一个
SELECT field1, field2, SUM(field3) FROM table1
GROUP BY field2
微软的 T-SQL 会抱怨,但是
MySQL 只会静默执行
SELECT whatever(field1), field2, SUM(....
这当然比SELECT max(field1), field2, SUM(.... GROUP BY field2
快得多
MySQL 支持ANY
,但SELECT ANY(field1) ...
不起作用,因为ANY
是类似于IN
和ALL
的运算符。
见:http://dev.mysql.com/doc/refman/5.0/en/any-in-some-subqueries.html
我喜欢 MySQL
【讨论】:
模棱两可且不明确 = 危险。 @gbn,很多工具都会给你一把枪来射击,这就是为什么你需要了解你的工具,这样你才不会在脚下开枪。是枪杀人还是人杀人完全是另一回事。 不好的类比:没有可比性。在这种情况下,我认为没有必要让 RDBMS 代表我猜测列。 只有 MySQL 也有这种歧义:SQL Server、Sybase、Oracle、PostGres 没有。见***.com/q/5986127/27535 多么奇妙的造词,非常恰当:idiology,如在 idio[tic] [ideo]logy 中,如在“MySQL 的意识形态”中。我会记住那个的。 (正确的拼写是ideology,顺便说一句。) @Johan - 携带你的枪支类似于它的结论 - 优质枪支(所有其他 RDBMS)给你一个安全开关,以防止意外射击。 MYSQL 为您提供了触发和过载弹药,让您更容易伤害自己。【参考方案3】:MIN 和 MAX 一样贵。
【讨论】:
我知道,但是还有其他更便宜的吗? @Luis - 如果该字段已编入索引,则否。MIN
和 MAX
在索引字段上只需转到索引中的第一个或最后一个条目。
@JNK:但 MIN() 或 MAX() 没有?
@Parkyprg:不,MIN
和 MAX
将使用索引(如果有的话)。
@JNK - 仅当您获得单个 MAX
而不是使用 GROUP BY
时才如此。如果您正在执行GROUP BY
,即使group_column,aggregated_column
上存在索引,它也不会跳到下一组。 so for some cardinalities a recursive CTE can be better【参考方案4】:
从 MySQL 5.7(2015 年 10 月发布)开始,实际上有一个功能! any_value(col)
明确满足了这一需求 - 有关详细信息,请参阅 documentation。
但是,重要的是要注意,它似乎仍然不能保证短路并且仍可能执行全扫描,因此可能无法实现更高效率的目标。如果 MySQL 对此很聪明,那么有一些机会,尽管测试是明智的。无论如何,在两种情况下它可能会有所帮助:
如果要聚合的值特别大且未编入索引,那么任何比较都会很昂贵。 如果利用max
或其他占位符聚合使代码中的意图变得不那么清晰。例如,max
可能暗示它的存在是有原因的,而不是从分组中获得“任何东西”,但any_value
会明确定义意图而无需额外评论。
玩具样品:
select
col,
any_value(a.val) as any_val
from (
select 'blue' as col, 3 as val
union all
select 'blue' as col, 2 as val
union all
select 'green' as col, 1 as val
) as a
group by col
【讨论】:
【参考方案5】:好的,让我们重新表述原来的问题。如果提供 EXISTS-aggregate 函数,而不是模棱两可且不是 SQL 标准的 ANY,那就太好了。
我曾多次使用“count(outer.column) > 0”来模仿“exists(outer.column)”,因为无论如何都会丢弃计数,所以这可能会更便宜。
【讨论】:
以上是关于在没有 ANY() 的情况下,哪个是最便宜的聚合函数的主要内容,如果未能解决你的问题,请参考以下文章