Postgres

时间:2016-09-01 22:15:47

标签: postgresql

在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的UNIONINTERSECT运算符 因为他们暗中将行李强行塞进去。

例如,如果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归结为UNIONINTERSECTINTERSECT ALL 涉及没有属性的表的运算符。

注:
人们可能想知道为什么会考虑这种关系。 但它们实际上非常有用,因为a 与零列的关系可以用作机制 在查询处理中使用true和false进行推理

关系{()}代表true和关系 {}代表false

1 个答案:

答案 0 :(得分:0)

UNIONINTERSECT返回4行的事实似乎是自相矛盾的 - 空元组都是相等的(在这种情况下UNION应该是元素较少)或空元组都不相等(在这种情况下INTERSECT应该有更少的元素)。

INTERSECT 更多结果行比输入关系更明显是疯了。

你应该把它带到pgsql-hackers列表或将其报告为bug。

但我不得不怀疑你的陈述,即这些问题具有任何实际价值:

  1. SELECT列表不符合标准。它们是PostgreSQL中最近推出的实现工件。是什么阻止您使用(符合SQL标准的)变体SELECT 1 FROM ...

  2. 如何将一个空元组的结果解释为true,将空结果解释为false?两个空元组的结果是什么意思? UNIONINTERSECT在此背景下的含义是什么?