如何从输入列表/数组创建单列SQL表?

时间:2012-08-20 15:56:23

标签: python sql postgresql psycopg2

我想知道如何将一个list / set / tuple从python(通过psycopg2)传递给postgres查询作为一列表。例如,如果列表是['Alice', 'Bob'],我希望表格为:

| Temp  |
+-------+
| Alice |
| Bob   |

如果有人在阅读下面的部分后有其他建议来实现我的结果,那也没关系。

背景

我有一个SQL表,它有三列感兴趣:

ID | Members | Group
---+---------+----------
1  | Alice   | 1
2  | Alice   | 1
3  | Bob     | 1
4  | Charlie | 1
5  | Alice   | 2
6  | Bob     | 2
7  | Alice   | 3
8  | Bob     | 4
9  | Charlie | 3

我想要一个包含特定成员组合的组表。请注意,成员可能在一个组中有多个项目(例如ID 1和2)。

对于['Alice']的输入,我想要她所在的组(现在)以及仅包含她(唯一)的组,如下所示:

Group | Type
------+--------
1     | present
2     | present
3     | present

输入['Alice', 'Bob']

Group | Type
------+--------
1     | present
2     | unique

从阅读开始看起来我正在寻找here描述的关系划分,为此,我需要做原始问题,因为输入来自在python中处理的Web表单。同样,也欢迎替代解决方案。

1 个答案:

答案 0 :(得分:3)

您需要创建一个子查询来创建成员计数,然后使用GROUP BY语句执行简单的除数查询,但是针对IN static_set子句而不是针对另一个表。因为这是python,所以你已经知道了静态集的大小。

我假设您已经有了一个数据库游标,该表名为GroupMembers

MEMBERSHIP_QUERY = '''
    SELECT gm.group, mc.memberscount = %(len)s AS type
      FROM groupmembers gm
      JOIN (SELECT "group", COUNT(DISTINCT members) as memberscount 
              FROM groupmembers
             GROUP BY "group") mc
      ON gm.group = mc.group
    WHERE gm.members IN %(set)s
    GROUP BY gm.group, mc.memberscount
    HAVING COUNT(DISTINCT gm.members) = %(len)s;
'''

def membership(members):
    # obtain a cursor
    for row in cursor.execute(MEMBERSHIP_QUERY, dict(len=len(members), set=members)):
        yield dict(group=row[0], type=row[1])

因此无需使用TEMP表来执行此查询。

如果确实需要TEMP表用于其他目的,.executemany()最容易插入一组行:

members = ['Alice', 'Bob']
cursor.execute('CREATE TEMP TABLE tmp_members (member CHAR(255)) ON COMMIT DROP;')
cursor.executemany('INSERT INTO tmp_members VALUES (%s);',
    [(name,) for name in members])

注意.executemany()需要一系列序列;每个条目都是一系列行数据,在这种情况下每个只包含一个名称。我生成一个单项元组列表来填充表格。

或者,您也可以使用映射序列并使用%(name)s参数语法(因此行数据序列变为[dict(name=name) for name in members])。