2016-09-01 63 views
3

使用UNION或相交的Postgres最簡單的可能的查詢的列是SQL重複排除與Postgres的

postgres=# select; 
-- 
(1 row) 

這個查詢的結果是具有單個 元組(行)的關係,即,空元組。 所以我們得到關係{()}

這顯然是語義上正確的。

現在假設您有一個關係foo,其中包含1個屬性 (value)和至少兩個元組(行)。例如,

foo 
---- 
value 
------ 
    1 
    2 

現在發出以下查詢

postgres=# select from foo; 
-- 
(2 rows) 

這是包{(),()},這是有道理的,因爲 我們是在一個空的屬性集投影和有foo中兩個元。

我想要做的就是把這個袋子強制成一套 並獲得{()}。 這可以用一組通過如下進行:

postgres=# select from foo group by(); 
-- 
(1 row) 

這是正確的爲好。

另一種可能性,在一般情況下,刪除重複 是使用UNIONINTERSECT運營商SQL 的,因爲他們含蓄地強迫袋裝入套。

因此,舉例來說,如果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的一個bug,當它歸結到UNIONINTERSECTINTERSECT ALL 運營商在事關表沒有任何屬性。

備註:
有人可能會問爲什麼會考慮這種關係。 但他們實際上是非常有用的,因爲零列的 關係可以用作查詢處理機制 辯解與真假

的關係{()}代表true和關係 {}代表false

+1

對不起,我不明白你的問題。請不要發明僞碼。 – wildplasser

+1

@wildplasser其實它是工作代碼。 – Abelisto

+0

比較'未知'和'未知'提供了'未知'結果[(Three-valued logic)](https://en.wikipedia.org/wiki/Three-valued_logic)這是因爲'未知'值的系列假設因爲它們都不同(或不同於其他方面)。 – Abelisto

回答

0

UNIONINTERSECT返回4行似乎自相矛盾–或是空的元組都相等(在這種情況下UNION應具有更少的元件)或空元組是所有不相等(事實上在這種情況下INTERSECT應該有更少的元素)。

INTERSECT更多結果行比任一輸入關係顯然是瘋了。

你應該把它帶到pgsql-hackers列表或者報告它是一個錯誤。

但我不得不懷疑你的話,這些問題是任何實用價值:

  1. SELECT列表是不符合標準。它們是PostgreSQL中最近推出的實現工件。什麼讓你不使用(SQL標準兼容)變種SELECT 1 FROM ...

  2. 如何解釋一個空元組的結果爲true,空結果爲false?兩個空元組的結果是什麼意思?在這種情況下,UNIONINTERSECT是什麼意思?