PostgreSQL - 检索字段的不同可能排列的数量

时间:2016-06-15 08:38:31

标签: python postgresql permutation psycopg2

这将是一个难以解释的问题,但请耐心等待。

我有一个数据库,例如:

Field_1    Field_2    Field_3
a          1          True
c          5          False
d          1          False
a          1          False
b          2          True

我有一个每个字段的值列表,我希望从中找到当前可能排列的数量:

Field_1_Values = [c, d]
Field_2_Values = [1, 2, 5]
Field_3_Values = [True]

我想计算数据库中存在的所有可能的排列长度,以计算不同字段之间所有可能的排列(顺序无关紧要)。

因此,在此示例中检查的排列将是:

Length_1: c, d, 1, 2, 5, True
Length_2: c-1, d-1, c-2, d-2, c-5, d-5, c-True, d-True, 1-True, 2-True, 5-True
Length_3: c-1-True, c-2-True, c-5-True, d-1-True, d-2-True, d-5-True, 

我正在寻找的结果是每个不同排列长度的记录总数:

Length_1_Total = 9
Length_2_Total = 4
Length_3_Total = 0

目前,我正在使用Python并在列表上循环,即

import psycopg2
import itertools

conn = psycopg2.connect(host=database_host, port=database_port, dbname=database_name, user=database_user, password=database_password)

cursor = conn.cursor()

Field_1_Values = ["field_1:c", "field_1:d"]
Field_2_Values = ["field_2:1", "field_2:2", "field_2:5"]
Field_3_Values = ["field_3:True"]

Length_1_Total = 0

for combo in itertools.chain(Field_1_Values,Field_2_Values,Field_3_Values):
    query = "select exists(select 1 from dataset where " + combo.split(":")[0] + " = %s)"

    cursor.execute(query, [combo.split(":")[1]])
    Length_1_Total += int([row[0] for row in cursor.fetchall()][0])

Length_2_Total = 0

for combo in itertools.chain(itertools.product(Field_1_Values, Field_2_Values), itertools.product(Field_1_Values, Field_3_Values), itertools.product(Field_2_Values, Field_3_Values)):
    query = "select exists(select 1 from dataset where " + combo[0].split(":")[0] + " = %s and " + combo[1].split(":")[0] + " = %s)"

    cursor.execute(query, [combo[0].split(":")[1], combo[1].split(":")[1]])
    Length_2_Total += int([row[0] for row in cursor.fetchall()][0])

Length_3_Total = 0

for combo in itertools.chain(itertools.product(Field_1_Values, Field_2_Values, Field_3_Values)):
    query = "select exists(select 1 from dataset where " + combo[0].split(":")[0] + " = %s and " + combo[1].split(":")[0] + " = %s and " + combo[2].split(":")[0] + " = %s)"

    cursor.execute(query, [combo[0].split(":")[1], combo[1].split(":")[1], combo[2].split(":")[1]])
    Length_3_Total += int([row[0] for row in cursor.fetchall()][0])

在上面的代码中 -

itertools.product为我提供了传递它的列表之间可能存在的排列。 itertools.chain允许我连接生成器,以便在循环运行时创建排列,而不是将它们全部存储在内存中。

现在实际上我有4000条记录,数据集中有5个字段。我还对不同的值列表执行上述过程50次(因为这些列表是一些先前工作的结果,我希望看到先前工作对可能的置换结果集的影响)。

这段代码变得非常慢,所以我想知道是否有办法让数据库直接在一个查询中完成所有工作,也许我可以从中获益一些数据库优化。

我的想法:

我确实想过要查询数据库中不同的值组合,然后检查这个结果集和我的长度为1的排列之间的交集,以便在我的Python代码中检查,即长度为1的排列:< / p>

query = """select distinct(Field_1)
           union all
           select distinct(Field_2)
           union all
           select distinct(Field_3)"""

cursor.execute(query)
Present_Length_1_Permutations = set([row[0] for row in cursor.fetchall()])

Length_1_Permutations_To_Check = set([c, d, 1, 2, 5, True])

Matching_Permutations = Length_1_Permutations_To_Check.intersection(Present_Length_1_Permutations)

Length_1_Total = len(Matching_Permutations)

分别重复长度为2和长度为3的排列过程。但是,在我的真实数据集中,我得到了一个“内存不足”错误&#39;对于某些较长的排列,因为数据库查询返回的结果集太大。

有没有办法可以直接在数据库中执行排列检查?那么我决不会将所有不同的排列返回到我的代码中吗?

即。类似的东西(我知道这是不正确的代码,只是试图提出我的想法),假设Length_1_Values是我的列表来检查是否存在:

select permutation from (select distinct(Field_1) union all select distinct(Field_2) union all select distinct(Field_3)) inner join permutation from Length_1_Values

0 个答案:

没有答案