使用NOT IN和NULL处理查询

时间:2017-07-30 13:23:31

标签: sql postgresql null psycopg2

我的应用程序允许用户匹配,我不希望他们在匹配结束后的间隔内匹配更多次。

我使用(zadd)匹配和unix时间戳存储在redis上。

在我的postgres查询中,所以我希望能够做到:

SELECT user_id FROM users WHERE user_id NOT IN %s

这只是子查询,其中有许多其他条件,但问题是当redis返回空列表时,因为用户在该间隔期间未处于活动状态,NOT IN()会返回错误。

处理它的最佳方法是什么?用例和什么时候?另外我想在默认情况下放一个假的负user_id在列表redis返回,但我不喜欢这个hack

编辑: 我的查询样本是:

UPDATE users SET status = %s WHERE user_id IN (SELECT user_id FROM users WHERE user_id NOT IN % LIMIT 1)

查询工作正常,但今天我在子查询中添加了部分user_id NOT in %s。我传递redis返回的元组(或者更好的redis返回一个列表并将其转换为元组)。它只包含[1234,356,678]等整数。它在元组不为空(内部至少有一个元素)时工作正常但如果元组为空则会出现此错误:

psycopg2.ProgrammingError: ERROR:  syntax error at or near ")"
LINE 1: ...ocked = 0 AND bot_lang = 'en' AND user_id NOT IN () ORDER BY...

确实我解决了这个问题,默认情况下在元组中添加了一个假的user_id,所以它永远不会是空的,但我不喜欢这个hack,我希望能够找到更好的解决方案。

3 个答案:

答案 0 :(得分:2)

而不是user_id NOT IN (%s)您可以使用user_id <> ALL(ARRAY[%s]::int[])NOT user_id = ANY(ARRAY[%s]::int[])(请注意,我建议从参数值中排除括号)

所以,对于非空列表:

select 1 <> all(array[1,2]::int[]);

和空列表

select 1 <> all(array[]::int[]);

两者都很好。

更新:对于psycopg2,更好的方法是让它解析参数格式。对于数组,它可能只是:

a = [1,2,3]
cursor.execute("... NOT user_id = ANY(%s) ...",(a,))

答案 1 :(得分:0)

Simpl tsql查询可以写成:

select * from table_name where coulmnName NOT IN ('value1','value2','value3')

例如:

select username from user where user NOT IN ('ranjeet', 'jha') 

其中user是table_name,username是columnname,&#39; ranjeet&#39;和&#39; jha&#39;两个提供的值。

答案 2 :(得分:0)

您可以在此处尝试异常处理。像这样的东西 -

select coalesce(username,0) from user where user NOT IN ('ranjeet', 'jha') 
or user IS NULL;