在Postgres中,最简单的查询是
postgres=# select;
--
(1 row)
此查询的结果是与单个关系的关系
元组(行),即空元组。
所以我们得到了关系{()}
。
这显然在语义上是正确的。
现在假设您有一个具有1个属性的关系foo (值)和至少两个元组(行)。例如,
foo
----
value
------
1
2
现在发出以下查询
postgres=# select from foo;
--
(2 rows)
这是包{(),()}
,这是有道理的
我们在一组空属性上进行投影,foo中有两个元组。
我想做的是将这个包强行塞进一套
并获得{()}
。
这可以通过以下方式与小组完成:
postgres=# select from foo group by();
--
(1 row)
这也是正确的。
一般来说,另一种可能性是删除重复项
是使用SQL的UNION
或INTERSECT
运算符
因为他们暗中将行李强行塞进去。
例如,如果R
是重复关系,
查询
(select * from R) UNION (select * R)
或查询
(select * from R) INTERSECT (select * R)
会做到这一点。
现在这是我的观察(和问题)。
考虑查询
(select from foo) UNION (select from foo)
可以预期这个查询的答案是
关系{()}
,即关系
删除重复的空元组。
但是,何时在postgresql中执行此查询
不要得到这个答案。
postgres=# (select from foo) UNION (select from foo);
--
(4 rows)
因此,在这种情况下似乎是UNION
运算符
行为与UNION ALL
运算符完全相同。
postgres=# (select from foo) UNION ALL (select from foo);
--
(4 rows)
但INTERSECT
发生了更奇怪的事情
运营商。考虑查询
postgres=# (select from foo) INTERSECT (select from foo);
--
(4 rows)
所以你再次获得4个空元组 只有1(或最多2)。
INTERSECT ALL
运算符
postgres=# (select from foo) INTERSECT ALL (select from foo);
--
(4 rows)
结论:似乎有一个错误
postgresql归结为UNION
,INTERSECT
和INTERSECT ALL
涉及没有属性的表的运算符。
注:
人们可能想知道为什么会考虑这种关系。
但它们实际上非常有用,因为a
与零列的关系可以用作机制
在查询处理中使用true和false进行推理
关系{()}
代表true
和关系
{}
代表false
。
答案 0 :(得分:0)
UNION
和INTERSECT
返回4行的事实似乎是自相矛盾的 - 空元组都是相等的(在这种情况下UNION
应该是元素较少)或空元组都不相等(在这种情况下INTERSECT
应该有更少的元素)。
INTERSECT
更多结果行比输入关系更明显是疯了。
你应该把它带到pgsql-hackers列表或将其报告为bug。
但我不得不怀疑你的陈述,即这些问题具有任何实际价值:
空SELECT
列表不符合标准。它们是PostgreSQL中最近推出的实现工件。是什么阻止您使用(符合SQL标准的)变体SELECT 1 FROM ...
?
如何将一个空元组的结果解释为true
,将空结果解释为false
?两个空元组的结果是什么意思? UNION
和INTERSECT
在此背景下的含义是什么?