雪花 - 聚合函数:SUM(*)、AVG(*)、MIN(*)、MAX(*)、ANY_VALUE(*)

问题描述 投票:0回答:1

以下语法起作用的可能原因是什么:

SELECT SUM(*), AVG(*), MIN(*), MAX(*), ANY_VALUE(*);

输出:

总和(*) 平均值(*) 最小(*) 最大(*) 任意_值(*)

数据类型:

DESCRIBE RESULT LAST_QUERY_ID();
/*
name    type    kind
SUM(*)  NUMBER(30,0)    COLUMN
AVG(*)  NUMBER(36,6)    COLUMN
MIN(*)  VARCHAR(0)  COLUMN
MAX(*)  VARCHAR(0)  COLUMN
ANY_VALUE(*)    VARCHAR(0)  COLUMN
*/

根据查询配置文件,解析为:

EXPLAIN USING TABULAR
SELECT SUM(*), AVG(*), MIN(*), MAX(*), ANY_VALUE(*);


提供表/子查询时

*
被解析为第一列:

SELECT SUM(*), AVG(*), MIN(*), MAX(*), ANY_VALUE(*)
FROM (VALUES (1)) sub(c);
/*
SUM(*)  AVG(*)  MIN(*)  MAX(*)  ANY_VALUE(*)
1   1   1   1   1
*/

但是,如果存在多于一列,则不起作用:

SELECT SUM(*), AVG(*), MIN(*), MAX(*), ANY_VALUE(*)
FROM (VALUES (1,2));

错误:函数 [SUM(VALUES.COLUMN1, VALUES.COLUMN2)] 的参数太多

还有:

SELECT SUM(*)
FROM (VALUES(1))
HAVING SUM(*) > 1;

仅在 SELECT 子句中允许使用 * 作为函数参数。


聚合函数的文档没有为

*
SUMMIN/MAX 等上下文中提供任何线索。

我正在寻找可能有用的有效用例。


编辑:

接受多个单一输入的聚合函数:

SELECT LISTAGG(*) FROM (SELECT 'a', 'b'); 
--error: argument 2 to function LISTAGG needs to be constant, found'"values"."'B'"'

但是:

SELECT MIN_BY(*) 
FROM (VALUES('a', 'b'), ('aa', 'a')) AS sub(c1, c2);
/*
MIN_BY(*)
aa
*/
snowflake-cloud-data-platform aggregate-functions
1个回答
1
投票

我的假设是它是来自

count(*)
的“魔法神器”,这确实是一个奇怪的表达。

是的,又不是。但考虑到解析器会看到

<inbuilt_built_function(token)><paren><star><paren>
count
是一个内置函数,其他函数也是如此。我认为 * 将充当“将所有输入放在这里”的模板。应该可以使用
count(distinct *)
进行测试,给出与
count(distinct a,b,c)
相同的结果(对于三列表)

因此,* 到“所有输入”的扩展只是自动魔术化,然后

sum(a,b)
未能通过 sum 的参数计数检查,这不是解析问题,也不是 AST 问题,而是几乎运行-时间问题。

测试:

select 
    count(*) as c1, 
    count(distinct *) as c2, 
    count(distinct column1, column2) as c3
from values 
    (1,2), 
    (1,2), 
    (null, null);

好吧,这并没有证明我的想法,但它确实表明标记器正在生成一个开始标记......:-)

更多大声思考:

select 
    count(*) as c1, 
    count(column1) as c2, 
    count(column2) as c3, 
    count(column1, column2) as c4, 
    
    --count(distinct *) as c2, 
    --count(distinct(column1, column2)) as c2, 
    count(distinct column1, column2) as c3
from values 
    (1,2), 
    (1,2), 
    (null, null);
    select 
    count(*) as c1, 
    count(column1) as c2, 
    count(column2) as c3, 
    count(column1, column2) as c4, 
    count(distinct column1, column2) as c3
from values 
    (1,2), 
    (1,2), 
    (null, null);

啊,是的,* 表示存在一行,作为显式名称,触发非空值,所以它是参数的扩展。但是整个 TYPE 类参数,计数必须理解的“行”,以及 SUM 和 MAX 等,可以处理,但只是自动魔术成“必须只有一列”。

超级弱的答案,因为自动魔法就像免费的午餐,“更好”。

或者它“令人恶心”,但是一些大客户有很多 SQL“无法更改,并且需要支持才能赚大钱,所以嘿为什么不呢?”我不喜欢这些,因为它们看起来太简单并且思维封闭。但它们作为选项而存在。

魔法行选项:

对于如何在 Medium 上进行 PIVOT 有一个非常好的解释,并且对于源的参数(未在结果列或独立于所选列的输出列中命名),它有一个隐式的

GROUPING BY ALL
,因此已经有一个概念“只要接受你所得到的所有东西,并理解它”就可以支持这一点。也许它就像 C 中的 ARGC、ARGV 或 C# 中的 params,它变成了一桶东西,被动态处理,因此出现 LISTAGG 错误,这确实显示了参数的想法。

这太有趣了!

© www.soinside.com 2019 - 2024. All rights reserved.