使用 NOT IN 和 NULL 处理查询
Handle query using NOT IN and NULL
我的应用程序允许用户进行匹配,但我不希望他们在匹配结束后的一段时间内进行更多次匹配。
我用 (zadd) 匹配项和 unix 时间戳存储在 redis 上。
在我的 postgres 查询中,所以我希望能够做到:
SELECT user_id FROM users WHERE user_id NOT IN %s
那只是子查询,where 中还有很多其他条件,但问题是当 redis returns 一个空列表时,因为用户在该时间间隔内没有活动,NOT IN () returns 一个错误。
最好的处理方法是什么?用例和什么时候?我还想在列表 redis returns 中默认放置一个假的否定 user_id,但我不太喜欢这个 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 returns 的元组传递给那里(或者更好的是 redis returns 一个列表,然后我将它转换成一个元组)。它只包含 [1234, 3456, 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,这样它就永远不会为空,但我不喜欢这种技巧,我希望能够找到一个更好的解决方案。
简单的tsql查询可以写成:
select * from table_name where coulmnName NOT IN ('value1','value2','value3')
例如:
select username from user where user NOT IN ('ranjeet', 'jha')
其中用户是 table_name,用户名是列名,'ranjeet' 和 'jha' 两个提供的值。
您可以在这里尝试异常处理。像这样 -
select coalesce(username,0) from user where user NOT IN ('ranjeet', 'jha')
or user IS NULL;
您可以使用 user_id <> ALL(ARRAY[%s]::int[])
或 NOT user_id = ANY(ARRAY[%s]::int[])
而不是 user_id NOT IN (%s)
(请注意,我建议从参数值中排除括号)
因此,对于非空列表:
select 1 <> all(array[1,2]::int[]);
对于空列表
select 1 <> all(array[]::int[]);
两者都很好。
Update: 对于psycopg2
更好的方法是让它解析参数的格式。对于数组,它可能只是:
a = [1,2,3]
cursor.execute("... NOT user_id = ANY(%s) ...",(a,))
我的应用程序允许用户进行匹配,但我不希望他们在匹配结束后的一段时间内进行更多次匹配。
我用 (zadd) 匹配项和 unix 时间戳存储在 redis 上。
在我的 postgres 查询中,所以我希望能够做到:
SELECT user_id FROM users WHERE user_id NOT IN %s
那只是子查询,where 中还有很多其他条件,但问题是当 redis returns 一个空列表时,因为用户在该时间间隔内没有活动,NOT IN () returns 一个错误。
最好的处理方法是什么?用例和什么时候?我还想在列表 redis returns 中默认放置一个假的否定 user_id,但我不太喜欢这个 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 returns 的元组传递给那里(或者更好的是 redis returns 一个列表,然后我将它转换成一个元组)。它只包含 [1234, 3456, 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,这样它就永远不会为空,但我不喜欢这种技巧,我希望能够找到一个更好的解决方案。
简单的tsql查询可以写成:
select * from table_name where coulmnName NOT IN ('value1','value2','value3')
例如:
select username from user where user NOT IN ('ranjeet', 'jha')
其中用户是 table_name,用户名是列名,'ranjeet' 和 'jha' 两个提供的值。
您可以在这里尝试异常处理。像这样 -
select coalesce(username,0) from user where user NOT IN ('ranjeet', 'jha')
or user IS NULL;
您可以使用 user_id <> ALL(ARRAY[%s]::int[])
或 NOT user_id = ANY(ARRAY[%s]::int[])
而不是 user_id NOT IN (%s)
(请注意,我建议从参数值中排除括号)
因此,对于非空列表:
select 1 <> all(array[1,2]::int[]);
对于空列表
select 1 <> all(array[]::int[]);
两者都很好。
Update: 对于psycopg2
更好的方法是让它解析参数的格式。对于数组,它可能只是:
a = [1,2,3]
cursor.execute("... NOT user_id = ANY(%s) ...",(a,))