2011-11-28 79 views
3

我有两个表,Foo和Bar,我想将它们连接在一起,以便BarID根据数组中的键获取奖励,或者如果没有设置数组,则默认情况下每个键均解锁奖项。postgresql XOR加入数组值或null?

>Table Foo 
fooID | someArray | prize 
---------------------------------- 
1 | {10,20,30} | 'Winner' 
2 | {10}   | 'Grand prize' 
3 | null   | 'Participant' 

(这不是对的someArray一个字符串,它是一个有效的postgresql type

>Table Bar 
BarID | Key 
------------ 
1 | 10 
2 | 20 
3 | 30 
4 | 40 
5 | 40 
6 | 40 

我试过下面这样:

SELECT 
    Foo.fooID, 
    Bar.prize 
FROM Foo 
LEFT JOIN Bar ON Bar.Key = ANY(someArray) 

我有这个收效甚微,当我在WHERE子句中输入如

WHERE Bar.BarID = 3 

我的结果只是'Winner'm,但我也想获得'参与者'。如果设置我在哪里,包括空值:

WHERE 
    Bar.BarID = 3 
    OR 
    Foo.someArray = null 

我还没有得到我的空值了。

否where子句返回值的所有组合,包括空值。

我不太确定如何得到我想要的这种行为。我可以全部获得,或者我只能获得一组值,但不能同时获得两组值。例如,如果我要为BarID = 1进行连接,则应该获得“获胜者”,“大奖”和“参与者”。如果我选择了BarID 5,我只会收到参与者。

回答

2

尝试:

Foo.someArray IS NULL 

当应用于NULL值等于运算符总是产生NULL,不TRUE。要测试列是否包含NULL值,您需要上述表达式,而不是 Foo.someArray = NULL

More about that in the manual

您还必须将其写入JOIN条件,而不是WHERE条款,正如@Michael所评论的。像:

LEFT JOIN Bar ON Bar.Key = ANY(Foo.someArray) OR Foo.someArray IS NULL 

如果你把它的WHERE子句中,你可能还会发现行,其中Foo.someArray IS NOT NULL,但有不同的奖品。对于LEFT JOIN,如果(且仅当)在Foo中找不到某个给定的Bar,NULL值,那么Foo(包括someArray)的所有列都将附加值。这会欺骗在WHERE条件的支票。

+1

这是正确的,虽然我不知道,这种变化将产生预期的结果。如果我明白什么是理想的结果。 –

+0

@ MichaelKrelin-hacker:好点。我赞赏我的回答,并添加了一些相关信息。 –

1

尝试

ON COALESCE(Bar.Key = ANY(someArray),TRUE) 
+0

这个表达式带有(理论上的)缺陷,如果'Bar.Key'为NULL,它也会产生TRUE,这不是我们想要的。 –

+0

是的,我认为它永远不会。 –