【问题标题】:Snowflake: "SQL compilation error:... is not a valid group by expression"雪花:“SQL 编译错误:...不是有效的按表达式分组”
【发布时间】:2020-03-17 23:16:30
【问题描述】:

如果不使用 CTE 或子查询,有没有办法使用与 GROUP BY 不同的汇总级别的 Window 功能? COUNT(*) 有效,但如果在 COUNT 中指定了列名或使用了 SUM 函数,则查询错误并显示“不是有效的 group by expression”。即使 PARTITION BY 列与 GROUP BY 相同,也会出现错误结果。

注释掉的行将导致查询失败。 正是针对这些类型的事物,人们首先想要使用 Window 功能。

create table sales (product_id integer, retail_price real, quantity integer, city varchar, state varchar);
insert into sales (product_id, retail_price, quantity, city, state) values 
(1, 2.00,  1, 'SF', 'CA'),
(1, 2.00,  2, 'SJ', 'CA'),
(2, 5.00,  4, 'SF', 'CA'),
(2, 5.00,  8, 'SJ', 'CA'),
(2, 5.00, 16, 'Miami', 'FL'),
(2, 5.00, 32, 'Orlando', 'FL'),
(2, 5.00, 64, 'SJ', 'PR');

select  city, state
,   count(*) as city_sale_cnt
,   count(*) over ( partition by state) as state_sale_cnt
--  ,   count(product_id) over ( partition by state) as state_sale_cnt2
,   sum(retail_price) as city_price
--  ,   sum(retail_price) over ( partition by state) as state_price

from sales
group by 1,2;

docs 表示 Window 功能可能会导致问题,包括含糊的警告“PARTITION BY 并不总是与 GROUP BY 兼容。”: 错误消息 SQL 编译错误:... is not a valid group by expression 通常表明 SELECT 语句的“项目”子句中的不同列的分区方式不同,因此可能会产生不同数量的行。

【问题讨论】:

    标签: sql count sum snowflake-cloud-data-platform window-functions


    【解决方案1】:

    注释掉的代码不正确。原因是窗口函数是在group by“之后”解析的,而group by之后没有product_idretail_price

    这很容易解决:

    select city, state,
           count(*) as city_sale_cnt,
           count(*) over (partition by state) as state_sale_cnt,
           sum(count(product_id)) over (partition by state) as ,
           sum(retail_price) as city_price,
           sum(sum(retail_price)) over ( partition by state) as state_price
    from sales
    group by 1, 2;
    

    起初,在聚合查询中使用窗口函数看起来有点混乱——嵌套聚合函数看起来很尴尬。我发现,虽然它的语法很容易习惯,但只要你用过几次。

    【讨论】:

    • 太棒了!太感谢了。根据结果​​,我认为 sum(count( 应该是 count(count 因为 state_sale_cnt 和 state_sale_cnt2 应该是相同的答案, count(count(product_id)) over ( partition by state) as state_sale_cnt2
    • @HarryD 。 . .如果这是你想要的,你可以使用count(*) over (partition by state)。这将返回结果集中给定state 的行数。
    【解决方案2】:

    虽然雪花可能会允许这样做(如 Gordon Linoff 所证明的那样),但我主张包装聚合查询并在外部查询中使用窗口函数。

    很少有 RDBMS 允许混合使用窗口函数和聚合,并且生成的查询通常难以理解(除非您是像 Gordon 这样的真正的 SQL 向导!)。

    select
        t.*,
        sum(city_sale_cnt) over (partition by state) as state_sale_cnt,
        sum(city_price) over ( partition by state) as state_price
    from (
        select  
            city, 
            state,
            count(*) as city_sale_cnt,
            sum(retail_price) as city_price
        from sales
        group by 1,2
    ) t;
    

    【讨论】:

    • 或者作为一个 CTE 也可能更好。
    • @MikeWalton:是的,它也可能是一个解决方案。
    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多