使用IN运算符比较多列

时间:2019-07-19 12:36:06

标签: python postgresql psycopg2

假设我具有以下架构:

CREATE TABLE keys (
    keytype INTEGER,
    keyvalue CHARACTER VARYING(30),
    object_id INTEGER NOT NULL
);
CREATE INDEX ix_keys ON keys (keytype, keyvalue);

我想搜索keytypekeyvalue的多个组合。一种方法是组合AND和OR,例如:

SELECT object_id FROM keys WHERE
    (keytype=1 AND keyvalue='ALICE') OR
    (keytype=1 AND keyvalue='BOB') OR
    (keytype=2 AND keyvalue='5552319912') OR
    (keytype=3 AND keyvalue='938477') OR
    ...

但是对于库(当前使用Python psycopg2,但可以是任何库),我想编写一个SQL并将元组列表作为参数发送。是否有运营商可以做到并仍然使用索引? (我知道IN仅适用于单列)

我知道这行不通:

find_keys = [
    (1, 'ALICE'),
    (1, 'BOB'),
    (2, '5552319912'),
    (3, '938477'),
]
cursor.execute("SELECT object_id FROM keys WHERE (keytype, keyvalue) IN %s", (find_keys,))

2 个答案:

答案 0 :(得分:3)

您实际上距离很近。将find_keys更改为元组的元组:

find_keys = (
    (1, 'ALICE'),
    (1, 'BOB'),
    (2, '5552319912'),
    (3, '938477'),
)
cur.execute("SELECT object_id FROM keys WHERE (keytype, keyvalue) IN %s", (find_keys,))

您不能使用列表,因为列表由psycopg2转换为数组。比较postgres中的对象集是有效的。

答案 1 :(得分:0)

我认为您可以这样做:

query = "SELECT object_id FROM keys WHERE (keytype, keyvalue) IN ((%s,%s))"
find_keys = [
    (1, 'ALICE'),
    (1, 'BOB'),
    (2, '5552319912'),
    (3, '938477'),
]

cursor.executemany(query, find_keys)

告诉我是否有效