检查psycopg2 / postgresql中是否存在python值列表

时间:2015-01-08 17:26:50

标签: python postgresql psycopg2 postgresql-9.0

我有一个python值列表和一个带有特定列的postgresql表。我想知道我的python列表中的每个元素是否在表中有任何行具有该ID。

例如,假设我有这个python列表:

vals = [4, 8, 15, 16, 23, 42]

以及查询:

select my_col from my_table;

给出:

[4, 5, 6, 7, 8]

然后我想要一个返回的查询:

[True, True, False, False, False, False]

我可以遍历列表并为每个值执行一个新的“select exists”,但我想知道是否有办法在一次调用中执行此操作?

我仅限于postgresql 9.0

2 个答案:

答案 0 :(得分:2)

这个问题更多的是关于SQL而不是aboyt Python或psycopg。我会使用类似的查询:

SELECT my_col = ANY(your_array_here) FROM my_table;

获得“表格顺序”或

的结果
SELECT A.x = ANY(SELECT my_col FROM my_table) 
  FROM (SELECT * FROM unnest(your_array_here) x) A;

以“vals order”获得结果。

幸运的是,psycopg提供了一个默认适配器,可以将Python列表转换为PostgreSQL数组,代码非常简单:

curs.execute("SELECT my_col = ANY(%s) from my_table", (vals,))

或:

curs.execute("""SELECT A.x = ANY(SELECT my_col FROM my_table) 
                  FROM (SELECT * FROM unnest(%s) x) A""", (vals,))

请注意,绑定变量参数应该是dict或元组,并且您希望将完整列表绑定到查询中的单个变量,这意味着您应该使用1元素元组({{1而不是试图直接传递(vals,)

答案 1 :(得分:1)

我认为这需要混合使用字符串格式和占位符(因为%s中每个项目需要一个vals):

vals = [4, 8, 15, 16, 23, 42]

query = 'select distinct(my_col) from my_table where my_col in ('
query += ', '.join(['%s'] * len(vals))
query += ')'

cursor.execute(query, vals)
theset = {t[0] for t in cursor.fetchall()}

theboollist = [v in theset for v in vals]

此方法应该保证您发送到数据库的数据量(where ... in子句)和您从中获取的数量都是O(N)其中N等于len(vals);我认为在大O方面做得比在逻辑上做得更好。