分组在聚合参数和NULL替换中设置列

时间:2015-10-29 13:11:48

标签: sql aggregate-functions aggregates grouping-sets

互联网上有许多分组集示例,例如下面示例中的查询Q1。但查询Q2是不同的,因为A2是分组列,它用作SUM()的参数。

根据SQL标准(自2003年以来的任何版本 支持分组集),以下哪一项适用于Q2?如果(1)是正确的,请参考标准解释原因。

  1. A2替换为NULL,除非它在聚合的参数中。这种解释将给出结果R1。这是Oracle的行为(看起来更有用)。

  2. A2替换为NULL,包括聚合中使用的位置:这意味着聚合将返回NULL。 这种解释将给出R2以下的结果。这就是我对SQL标准的理解(可能不正确)。

  3. 示例代码:

    List

    我从SQL 2003 7.9语法17中了解到这一点,它描述了如何用NULL替换列。但是,我可能错过或误解了其他地方的规则,该规则排除了聚合的参数。

    -- Setup
    create table A (A1 int, A2 int, A3 int);
    insert into A values (1, 1, 100);
    insert into A values (1, 2, 40);
    insert into A values (2, 1, 70);
    insert into A values (5, 1, 90);
    
    -- Query Q1
    -- Expected/Observed results:
    --
    --         A1         A2    SUM(A3)
    -- ---------- ---------- ----------
    --          1          -        140
    --          2          -         70
    --          5          -         90
    --          -          1        260
    --          -          2         40
    --          -          -        300
    select A1, A2, sum (A3)
    from A
    group by grouping sets ((A1), (A2), ())
    order by 1, 2;
    
    -- Query Q2
    -- Results R1 (Oracle):
    --         A1         A2    SUM(A2)
    -- ---------- ---------- ----------
    --          1          -          3
    --          2          -          1
    --          5          -          1
    --          -          1          3
    --          -          2          2
    --          -          -          5
    -- 
    -- Results R2 (SQL Standard?):
    --         A1         A2    SUM(A2)
    -- ---------- ---------- ----------
    --          1          -          - 
    --          2          -          - 
    --          5          -          - 
    --          -          1          3
    --          -          2          2
    --          -          -          -   -- NULL row
    select A1, A2, sum (A2)
    from A
    group by grouping sets ((A1), (A2), ())
    order by 1, 2;
    

1 个答案:

答案 0 :(得分:0)

与许多困难的SQL功能一样,它可以帮助查看标准的早期版本,其中措辞可能更简单。事实证明,分组集在SQL 1999中引入,然后在SQL 2003中进行了修订。

SQL 1999

语法规则4声明:

Let SING be the <select list> constructed by removing from SL every <select
sublist> that is not a <derived column> that contains at least one <set
function specification>.

然后,语法规则11将PC_k定义为分组中包含的列引用。它构造了一个派生表,用于投射GSQQL_i的并集,它是适当地投射PC_k或NULL的查询规范,PCBIT_i分组函数指标和SING

因此任何包含set函数的都不会替换它的参数,也不会替换它的列。所以答案(1)是正确的。

但是,在下面的查询中,与GSQQL_i对应的<grand total>不会被C1分组,因此我认为它会给出错误,而不是将C1替换为该分组集的NULL。

select C1 + MAX(C2) from T group by grouping sets ((C1), ());

SQL 2003 - 2011

我仍然没有对此有明确的答案。它取决于他们的意思(或忘记指明?)&#34;引用&#34;在替换规则中。如果说其中一个&#34;立即包含&#34;,&#34;简单地包含&#34;将会更清楚。或&#34;直接包含&#34;,如ISO 9075-1(SQL第1部分:框架)中所定义。

“一般规则”开头的注释(SQL 2003中的编号134)表示&#34;作为a 语法规则中指定的句法转换的结果 子条款,只有原始&lt; group by子句&gt; s留待考虑。&#34;所以 聚合论证要么已经或者没有被取代:我们不是 期望以特殊方式评估聚合(如果一般规则3在语法规则17的NULL替换之前生效,那么答案(1)将是正确的。)

我找到了技术勘误5 [pdf]的草案,这是一个&#34;差异&#34;对于SQL 2003.这包括第80-87页的相关更改。不幸的是,大部分变化只有简短的理由&#34;提供正确,统一的CUBE和ROLLUP&#34;处理。上面引用的一般规则3有理由&#34;澄清列引用的语义和#34;。