3

我有一个 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]

我可以遍历列表并为每个值执行一个新的“选择存在”,但我想知道是否有办法在一次调用中做到这一点?

我仅限于 postgresql 9.0

4

2 回答 2

3

这个问题更多的是关于 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,))

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

于 2015-01-08T20:19:13.523 回答
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 做得更好。O(N)Nlen(vals)

于 2015-01-08T18:02:57.380 回答