You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DuckDB中通过宏实现按列列表进行GROUP BY分组?

动态生成GROUPING SETS(CUBE)聚合查询的宏解决方案

数据结构与样本数据

测试用表结构及初始化数据:

CREATE TABLE sample_table (
    YEAR INTEGER,
    BRAND VARCHAR, 
    PRODUCT VARCHAR,  
    SALES INTEGER     
);

INSERT INTO sample_table (YEAR, BRAND, PRODUCT, SALES) VALUES
(2023, 'AX', 'A', 10),
(2024, 'AX', 'A', 20),
(2024, 'AX', 'B', 70),
(2022, 'AY', 'C', 20),
(2023, 'AY', 'C', 90)
;

需求目标

创建一个宏,仅传入列名列表(如BRAND、PRODUCT),即可生成与以下SQL完全等效的查询结果:

SELECT YEAR, BRAND, PRODUCT, SUM(SALES) 
FROM SAMPLE_TABLE 
GROUP BY YEAR, GROUPING SETS(CUBE(BRAND, PRODUCT));

错误尝试与问题分析

用户最初编写的宏代码:

CREATE OR REPLACE MACRO MSUM(
    GRPCOLS
) AS TABLE (
    FROM TBL
    SELECT 
        COLUMNS(C -> (LIST_CONTAINS(GRPCOLS, C))),
        SUM(SALES)
    GROUP BY YEAR, GROUPING SETS(CUBE(COLUMNS(C -> LIST_CONTAINS(GRPCOLS, C))))
);

WITH TBL AS (SELECT * FROM SAMPLE_TABLE)
FROM MSUM([BRAND, PRODUCT]);

执行后触发报错:

Binder Error: STAR expression is not supported here

问题根源:COLUMNS()属于星型表达式,Snowflake不允许在GROUP BY子句中使用该类表达式。

可行解决方案

核心思路

通过动态SQL生成合法的GROUP BY子句:将传入的列名列表展开并拼接成标准列名序列,嵌入到CUBE()中,规避星型表达式的限制。

正确宏定义

CREATE OR REPLACE MACRO MSUM(grp_cols) AS TABLE (
    EXECUTE IMMEDIATE $$
        SELECT
            YEAR,
            $$ || LISTAGG(VALUE, ', ') FROM TABLE(FLATTEN(INPUT => ?)) || $$,
            SUM(SALES) AS total_sales
        FROM sample_table
        GROUP BY YEAR, GROUPING SETS(CUBE( $$ || LISTAGG(VALUE, ', ') FROM TABLE(FLATTEN(INPUT => ?)) || $$ ))
    $$ USING grp_cols, grp_cols
);

调用示例

直接传入列名列表即可执行查询:

SELECT * FROM MSUM(['BRAND', 'PRODUCT']);

结果说明

执行后会生成与目标SQL完全一致的聚合结果,包含YEAR、指定分组列的所有CUBE组合,以及对应的销售总额。

内容的提问来源于stack exchange,提问作者Rooh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 18:40:20