来自多个表的复杂SUM

时间:2014-07-13 05:04:17

标签: sql sqlite group-by sum django-orm

以下是我的表格:

CREATE TABLE component
                            (id INTEGER PRIMARY KEY AUTOINCREMENT,
                            name TEXT UNIQUE);

CREATE TABLE file
                            (id INTEGER PRIMARY KEY AUTOINCREMENT,
                            component_id INTEGER,
                            name TEXT UNIQUE);

CREATE TABLE function
                            (id INTEGER PRIMARY KEY AUTOINCREMENT,
                            file_id INTEGER,
                            name TEXT,
                            FOREIGN KEY(file_id) REFERENCES file(id),
                            UNIQUE(file_id, name));

CREATE TABLE version
                            (id INTEGER PRIMARY KEY AUTOINCREMENT,
                            version TEXT UNIQUE);

CREATE TABLE data
                            (id INTEGER PRIMARY KEY AUTOINCREMENT,
                            file_id INTEGER,
                            version_id INTEGER,
                            function_id INTEGER,
                            errors INTEGER,
                            ...,
                            FOREIGN KEY(file_id) REFERENCES file(id),
                            FOREIGN KEY(version_id) REFERENCES version(id),
                            FOREIGN KEY(function_id) REFERENCES function(id),
                            UNIQUE(file_id, version_id, function_id));

我需要两个查询:

  • 一个用于汇总文件中所有数据的data.errors。对于给定的文件ID,我需要所有错误的总和。
  • 一个用于汇总特定组件内所有文件的所有函数的data.errors。
  • 所有data.errors必须属于最新的version_id。

上述版本MAX要求的示例:

DATA
id  file_id     version_id  function_id     errors
1       1           3           1           40
2       1           3           2           231
3       1           2           3           19

这里我需要它返回ids 1,2并忽略3 ,即使它是特定功能的最新版本。它与属于该文件的函数的最新版本匹配。想象一个真实世界的场景,其中从新版本的文件中删除了一个函数。

唯一的要求是查询尽可能快。 数据库中的约束条件没有太大变化(最好没有任何变化)。 如果可以在Django ORM中进行,我打算使用它,这将是很好的但不是必需的。

1 个答案:

答案 0 :(得分:1)

最新版本的文件可以这样计算:

SELECT MAX(version_id)
FROM data
WHERE file_id = ?

这可以简单地插入到另一个查询中以获得总和:

SELECT SUM(errors)
FROM data
WHERE file_id = ?
  AND version_id = (SELECT MAX(version_id)
                    FROM data
                    WHERE file_id = ?)

要将其扩展到组件,需要另一个子查询来查找组件的文件:

SELECT SUM(errors)
FROM data
WHERE file_id IN (SELECT id
                  FROM file
                  WHERE component_id = ?)
  AND version_id = (SELECT MAX(version_id)
                    FROM data
                    WHERE file_id IN (SELECT id
                                      FROM file
                                      WHERE component_id = ?))