【问题标题】:How do I create a one-column SQL table from an input list/array?如何从输入列表/数组创建单列 SQL 表?
【发布时间】:2012-08-20 15:56:23
【问题描述】:

我想知道如何将列表/集合/元组从 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 表单中获取的。同样,也欢迎替代解决方案。

【问题讨论】:

  • 请注意,对于'Alice',所有三个组的第一个表都应该是present'Charlie' 也在第 3 组中。
  • 正确。当我更改示例时忘记更新。

标签: python sql postgresql psycopg2


【解决方案1】:

您需要创建一个子查询来创建成员计数,然后使用 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])。

【讨论】:

  • 这对我来说有两个问题。最后一行的 GROUP BY 引发错误,因为第 1 行的“=”不是聚合函数。在某些情况下,使用 SELECT DISTINCT 不会给出正确的结果。我已经用进一步的条目更新了表格以进行演示 - 该查询不再适用于 ['Alice', 'Bob'],因为第 3 组有 2 个成员,但他们是错误的。
  • 这很有道理,感谢您的帮助。为了完整起见,您也可以回答原始问题吗?否则,如果没有其他人这样做,我会接受这个作为正确答案。
猜你喜欢
  • 2020-06-26
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 2017-08-27
  • 2020-02-27
  • 1970-01-01
  • 2019-06-01
  • 1970-01-01
相关资源
最近更新 更多