【发布时间】:2014-08-21 11:43:15
【问题描述】:
我有一个包含以下表格的数据库:
function
id | name
version
id | name
data_table
id | function_id | version_id | date | arbitrary_data1
我通过解析文件插入数据。 如果一个函数在新版本中发生了变化,我会存储该函数的差异。 如果它没有改变,即使新版本中实际存在该函数,也不会插入数据。 所以从技术上讲,如果文件中的函数已更新,我只会存储新数据。
现在我需要一些复杂的查询,使基于差异的数据库看起来像一个普通的数据库, 每个版本都有之前版本的完整数据。
data_table 可能包含的内容示例:
data_table
id | function_id | version_id | date | arbitrary_data
1 1 1 2012-01-01 0
2 2 1 2012-01-01 150
3 1 2 2012-01-02 100
我需要一个查询,它为我提供特定功能的每个版本的任意数据和日期。
function_id=1 的预期结果示例:
date | arbitrary_data
2012-01-01 0 <-- version 1
2012-01-02 100 <-- version 2
我遇到的问题是由于“此”版本中未更新文件时缺少行。例如,如果我要提取函数 #2 的数据,则不会返回第二个版本的数据,因为它没有插入数据库中。
现在的挑战是为每个版本生成完整的数据(每个文件的数据)。
查询需要: 为每个版本选择任意数据和日期;如果没有特定版本的条目:查找最新的先前文件条目和 而是从该行中选择任意数据。 (日期仍应从原始行/版本中选择)
它必须与 SQLite 兼容并且最好是快速的。
我有一组查询结合 Python 中的一些逻辑/脚本来执行此操作,但每个版本的执行时间约为 1 秒;这对于我需要的东西来说太慢了。下面是 Python 代码:
def get_data(self, function_id):
#fvs is short for fileversions!
#Gets the function ID and for each version ID
all_fvs = self._conn.execute('''SELECT * FROM
(SELECT id as function_id FROM function WHERE id = ?)
CROSS JOIN
(SELECT id as version_id from version)
''', [function_id]).fetchall()
#Gets the function ID for each version ID that has been registered to the data_table
registered_fvs = self._conn.execute('''SELECT function_id, version_id
FROM data_table
WHERE function_id = ?
LIMIT 1
''', [function_id]).fetchall()
#Gets the function ID for each version ID that has been registered to the data_table with incomplete arbitrary_data
incomplete_registered_fvs = self._conn.execute('''SELECT arbitrary_data, version_id
FROM data_table
WHERE (arbitrary_data IS NULL OR date IS NULL)
GROUP BY version_id''').fetchall()
#Gets the arbitrary_data we want for all the rows corresponding to registered_fvs
data_set = self._conn.execute('''SELECT arbitrary_data, date from data_table
WHERE function_id = ?
''', [function_id]).fetchall()
#Converts the lists to counters so that we can perform set operations on them
all_fvs_counter = Counter(all_fvs)
registered_fvs_counter = Counter(registered_fvs)
incomplete_registered_fvs_counter = Counter(incomplete_registered_fvs)
#Filter out the registered fvs from all fvs
non_registered_fvs = (all_fvs_counter-registered_fvs_counter)-incomplete_registered_fvs_counter
#For all the versions that aren't registered, we fetch the latest value of a previous version which was registered
for (function, version) in non_registered_fvs:
data_set.append(self._conn.execute('''SELECT arbitrary_data, date
FROM data_table
WHERE function_id = ?
AND date <= (SELECT date FROM data_table WHERE version_id = ? LIMIT 1)
ORDER BY date DESC
LIMIT 1
''', [function, version]).fetchone())
return data_set
【问题讨论】:
-
@dani-h 。 . .样本数据和期望的结果有助于澄清问题。
-
“对于每个版本”是否意味着查询必须返回所有版本的数据,还是一个特定版本的数据?
-
适用于所有版本。基本上,如果缺少文件数据,则从最新版本中获取数据并将其添加到缺少的版本中。我不知道如何解释得更清楚。
标签: sql sqlite group-by where-clause