【问题标题】:Checking existence of list of python values in psycopg2/postgresql检查 psycopg2/postgresql 中是否存在 python 值列表
【发布时间】:2015-03-06 21:59:36
【问题描述】:

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

【问题讨论】:

  • 为什么不在select之后使用两行Python?将结果放入集合s,然后只需[x in s for x in vals]
  • 那么将整个DB列拉入python?那会奏效。它会在某个时候有几亿个条目,所以不确定这是否会对性能有点不利? (该列将被索引。)
  • 该示例仅用于说明 - 我并没有真正选择代码中的完整列。

标签: python postgresql psycopg2 postgresql-9.0


【解决方案1】:

这个问题更多的是关于 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 或元组,并且您希望将完整列表绑定到查询中的单个变量,这意味着您应该改用单元素元组 ((vals,))尝试直接传递vals

【讨论】:

  • 这是完美的 - 非常感谢。你说得对,这更像是一个 sql 问题!
【解决方案2】:

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

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 做得更好。

【讨论】:

  • 使用select distinct my_col保证len(cursor.fetchall()) <= N会有帮助吗?
  • @unutbu 当然,如果my_col 中可能存在重复,则没有考虑过这种情况,现在正在编辑修复,tx。
猜你喜欢
  • 2010-12-24
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
  • 2018-07-26
  • 2013-08-07
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
相关资源
最近更新 更多