这将是一个难以解释的问题,但请耐心等待。
我有一个数据库,例如:
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