互联网上有许多分组集示例,例如以下示例中的查询 Q1。 但是查询 Q2 是不同的,因为 A2 是一个分组列,它用作 SUM(( 的参数。
根据 SQL 标准(
A2 替换为 NULL,除非它在聚合的参数中。 这种解释将给出以下结果R1。 这是Oracle的行为(似乎更有用(。
A2 由 NULL 替换,包括它在聚合中的使用位置:这意味着聚合将返回 NULL。这种解释将给出以下结果R2。 这就是我对SQL标准的理解(可能是错误的(。
示例代码:
-- 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;
我从 SQL 2003 7.9 语法 17 中了解到这一点,它描述了如何将列替换为 NULL。 但是,我可能错过或误解了其他地方将参数排除为聚合的规则。
m) For each GS_i:
iii) Case:
1) If GS_i is an <ordinary grouping set>, then
A) Transform SL2 to obtain SL3, and transform HC to obtain
HC3, as follows:
II) Replace each <column reference> in SL2 and HC that
references PC_k by "CAST(NULL AS DTPCk)"
与许多困难的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(是正确的。
但是,在下面的查询中,对应于<grand total>
的GSQQL_i
不会按 C1 分组,因此我认为它会给出错误,而不是将该分组集的 C1 替换为 NULL。
select C1 + MAX(C2) from T group by grouping sets ((C1), ());
SQL 2003 - 2011
我仍然没有明确的答案。 这取决于替换规则中"引用"的含义(或忘记指定? 如果它说ISO 9075-1(SQL第1部分:框架(中定义的"立即包含","简单包含"或"直接包含"之一会更清楚。
一般规则开头的注释(SQL 2003 中的第 134 号(说:"作为此语法规则中指定的句法转换的结果子句,只剩下原始<按子句分组>来考虑。 所以聚合参数实际上已被替换或尚未被替换:我们不是期望以特殊方式评估聚合(而如果在语法规则 17 的 NULL 替换之前应用了一般规则 3,则答案 (1( 是正确的(。按子句分组>
我找到了技术勘误5 [pdf]的草稿,这是对SQL 2003的"差异"。 这包括对第 80-87 页的相关更改。 不幸的是,大部分更改只有简短的理由"提供对 CUBE 和 ROLLUP 的正确、统一的处理"。 上面引用的一般规则3的基本原理是"澄清列引用的语义"。