PostgreSQL XOR - 如何检查是否只填写了1列?

时间:2013-11-04 14:16:31

标签: postgresql logical-operators

如何在PostgreSQL中模拟XOR函数?或者,至少,我认为这是一种XOR类型的情况。

让我们说数据如下:

id | col1 | col2 | col3
---+------+------+------
1  | 1    |      | 4
2  |      | 5    | 4
3  |      | 8    | 
4  | 12   | 5    | 4
5  |      |      | 4
6  | 1    |      | 
7  |      | 12   | 

我想为那些只填充其中一列的行返回1列。(暂时忽略col3 ..

让我们从这个2列的例子开始:

SELECT
    id, COALESCE(col1, col2) AS col
FROM
    my_table
WHERE 
    COALESCE(col1, col2) IS NOT NULL -- at least 1 is filled in
AND
    (col1 IS NULL OR col2 IS NULL) -- at least 1 is empty
;

这很有效,应该导致:

id | col
---+----
1  | 1  
3  | 8   
6  | 1  
7  | 12

但是现在,我想以类似的方式包含col3。像这样:

id | col
---+----
1  | 1  
3  | 8 
5  | 4  
6  | 1  
7  | 12

如何做到这一点是一种更通用的方式? Postgres是否支持这种方法?

我找不到类似的东西。

3 个答案:

答案 0 :(得分:4)

填写正好1列的

行:

select * from my_table where
   (col1 is not null)::integer 
   +(col1 is not null)::integer 
   +(col1 is not null)::integer 
   =1

1或2行

select * from my_table where
   (col1 is not null)::integer 
   +(col1 is not null)::integer 
   +(col1 is not null)::integer 
   between 1 and 2

答案 1 :(得分:1)

“case”语句可能是你的朋友,“min”聚合函数不会影响结果。

select id, min(coalesce(col1,col2,col3))
from my_table
group by 1
having sum(case when col1 is null then 0 else 1 end+
           case when col2 is null then 0 else 1 end+
           case when col3 is null then 0 else 1 end)=1

[编辑] 好吧,我发现没有使用聚合函数的更好的答案,它仍然基于“案例”的使用,但我认为更简单。

select id, coalesce(col1,col2,col3)
from my_table
where (case when col1 is null then 0 else 1 end+
       case when col2 is null then 0 else 1 end+
       case when col3 is null then 0 else 1 end)=1

答案 2 :(得分:0)

怎么样

select coalesce(col1, col2, col3)
from my_table
where array_length(array_remove(array[col1, col2, col3], null), 1) = 1