大家好,提前谢谢你们的时间。
ansi sql标准定义了集合运算符union、except和intersect。
每一个都有两个变体-不同的和所有的。
此外,每种类型都可以是set或multiset类型。
阿法伊克:
只有postgresql支持except和intersect的all变量。
只有oracle支持多集。
更新-schwern在评论中告诉我mariadb也支持all for set操作符
对于这个问题,我将使用一个except示例,尽管intersect也是如此。
ansi sql(iso/iec cd 9075-2)标准定义如下:
第454页第7.16节“查询表达式”-第16项:如果在“查询项”或“查询表达式体”中指定了集合运算符,则:a)让t1、t2和tr分别为第一个操作数、第二个操作数以及“查询项”或“查询表达式体”的结果。b) 让tn1和tn2分别为t1和t2的有效名称。c) 如果集合运算符是union distinct、EXPECTALL、EXPECTDISTINCT、intersect all或intersect distinct,则t1和t2的每列都是分组运算的操作数。。。
第54页第4.10节集合类型-第6.2项:multiset except是计算两个multiset的multiset差的运算符。有两种变体,全部和不同。由结果中所有位置指定的变量,其值的示例数等于第一个操作数中该值的示例数减去第二个操作数中该值的示例数。distinct指定的变量从结果中删除重复项。
考虑到这一点,请考虑以下脚本(postgresql 12):
CREATE TABLE T1 (C1 INT);
CREATE TABLE T2 (C1 INT);
INSERT INTO T1 VALUES (1), (2), (2), (3), (3), (3);
INSERT INTO T2 VALUES (3);
SELECT * FROM T1
EXCEPT DISTINCT
SELECT * FROM T2;
SELECT * FROM T1
EXCEPT ALL
SELECT * FROM T2;
DROP TABLE T1, T2;
except distinct(默认)的结果与预期一样:2行中有1,2。
结果不是我所期望的。它返回5行3,3,2,2,1。
postgresql文档证实了这一行为,但是基于ansi定义,我希望只返回3行2,2,1。
第一个引号表示distinct将分组操作应用于限定该操作的行。本例3中的imho不应限定except,因此根本不应返回。
减法(m-n)元素的行为似乎与上面第二个引号中定义的多集操作相关联。然而,postgresql文档声明它甚至不支持基本的multiset,当然那些要求我们显式地指定multiset,除了all
我错过了什么?
根据我收到的评论和回复,我想澄清一下,我明白除all外,all在这里做什么。postgresql文档对此很清楚。我的问题是,这是否是正确的行为(集)除了所有。我的理解是,这是什么多集除了一切是为了。
事先谢谢你的想法。
安全健康!
2条答案
按热度按时间noj0wjuj1#
EXCEPT
将为您提供消除表中存在的值的不同结果。类似于MINUS
关系代数中的算子。以你为例,INSERT INTO T1 VALUES (1), (2), (2), (3), (3), (3);
INSERT INTO T2 VALUES (3), (3), (3);
zmeyuzjn2#
经过更多的研究和对标准的解读,我相信我最初的假设是错误的,postgresql的行为是正确的。
关于分组的引号既指distinct也指all。我应该看看p462-463,标准解释了:
案例:
a) 如果没有指定set运算符,那么t是指定的结果。
b) 否则:
i) 设d为t的度数。
ii)对于每个i,1(一)≤ 我≤ d:是的
14设dtci为t的第i列的声明类型。
让tcn1i成为t1的第i列的有效名称。
设tcn2i为t2第i列的有效名称。
让et1的形式为select cast(tcn11为dtc1)、cast(tcn12为dtc2)、…、cast(tcn1d为dtcd)
让et2的形式为select cast(tcn21为dtc1)、cast(tcn22为dtc2)、…、cast(tcn2d为dtcd)
iii)t包含以下行:
设r是et1中某一行或et2中某一行或两者的重复行。设m是et1中r的重复数,n是et2中r的重复数,其中m≥ 0和n≥ 0
如果指定了distinct或implicit,则
案例:
a) 如果指定了并集,则
案例:
i) 如果m>0或n>0,那么t正好包含r的一个副本。
ii)否则,t不包含r的副本。
b) 如果指定了except,则
案例:
i) 如果m>0且n=0,那么t正好包含r的一个副本。
ii)否则,t不包含r的副本。
c) 如果指定了intersect,则
案例:
i) 如果m>0,n>0,那么t正好包含r的一个副本。
ii)否则,t不包含r的副本。
3) 如果指定了all,则
案例:
a) 如果指定了并集,则t包含的r的重复数为(m+n)。
b) 如果指定了except,则t包含的r的副本数是(m–n)和0(零)的最大值。
c) 如果指定了intersect,那么t包含的r的重复数是m和n的最小值。