在没有索引外键的情况下在SQLite数据库中交叉查询多个表

时间:2016-04-14 17:50:26

标签: sql database sqlite database-design database-schema

我正在研究一个研究项目,使用IMDb数据集作为我的辅助数据来源。我从IMDb本身提供的.ftp服务器下载文本格式的整个数据库,并使用IMDbPY python包将所有未排序的信息编译到关系数据库中。我选择使用SQLite作为我的SQL引擎,因为它能够创建本地存储的数据库,因此它似乎是最不麻烦的选择。经过一番探索和大量的文档阅读后,我最终得到了一个9.04 GB的im.db文件,托管了整个IMDb。

现在我需要根据我的要求隔离我的数据集,但由于我缺乏SQL经验,我发现很难找到最佳的方法。

具体来说,我想看一下:

  • 仅限电影(即不包括电视剧,剧集等);
  • 在2000年至2015年期间生产,包括在内;
  • 特征长度(即超过40分钟的运行时间);
  • 非成人(我甚至不知道IMDb主持有关这些的信息,但显然是这样);
  • 在美国制作;
  • 有关船员的完整信息。

Here's表示我的数据库架构。我对IMDbPY创建者所做的一些数据库设计选择感到困惑,但我不是SQL专家,这就是我的工作。一些澄清:

  • 标题表包含有关电影,节目,剧集等每个实例的基本信息,共计3,673,485行。 id 列是一个自动递增的主键,在所有其他相关表中被引用为 movie_id 外键。但是,似乎其他表中没有任何外键被正确编入索引,所以我不能仅仅通过了解特定电影的 id 值就可以使用简单的查询语句来正确获取必要的信息。
  • 正在运行SELECT count(*) FROM title WHERE kind_id=1 AND production_year BETWEEN 2000 AND 2015;告诉我,在2000 - 2015年之间有442,135个电影实例。到目前为止一切顺利。
  • complete_cast comp_cast_type 表格包含有关电影剧组/演员表的完成状态的信息。由于我只需要考虑具有完整工作人员信息的电影,我只需要隔离那些实例,其中(i) movie_id 存在于我之前的查询中(即442,135个电影行中); (ii) subject_id = 2; (iii) status_id = 3或4。
  • 这对我来说很棘手。 movie_info 表包含2000万行有关电影和电视节目的信息,包括运行时,流派,制作国家,制作年份等。基本上我需要隔离数据集的所有信息。在该表中(i) id 是任意自动递增的主键; (ii)movie_id是指来自 title id 值; (iii) info_type_id 指的是表 info_type 中列出的113种信息之一; (iv) info 保存实际信息,如整数或字符串。

  • 例如:正在运行SELECT id FROM title WHERE title='2001: A Space Odyssey' AND kind_id=1;会返回'2484213'。运行SELECT info FROM movie_info WHERE movie_id=2484213 AND info_type_id=1;返回'142,161,149',表示电影的三个可用版本的运行时间(以分钟为单位)。运行SELECT info FROM movie_info WHERE movie_id=2484213 AND info_type_id=8返回'USA,UK',表示参与生产的国家/地区。等等。

基本上我正在尝试创建一个新表,只填充符合我要求的电影,而且我很难找到最有效的方法。以下是我将需求转换为基本SQL语法的方法:

  • SELECT * FROM title WHERE kind_id=1 AND production_year BETWEEN 2000 AND 2015;
  • 然后来自 movie_info 表的一系列要求,这些要求仅交叉引用那些 movie_id 在查询中作为 id 存在的实例上述,和(i)info_type_id=1 AND info>40;(ii)info_type_id=3 AND info!='Adult';(iii)info_type_id=8 AND info='USA';
  • 最后,我需要确保所有选择都存在于 complete_cast 表中,WHERE subject_id=2 AND status_id=3 OR 4;

我一直在阅读SQLite文档,并怀疑我需要使用INNER / LEFT OUTER JOIN,EXISTS和UNION / INTERSECT / EXCEPT语句的某种组合,但不确定如何准确地处理它。我想有效地编写这段代码,因为按要求执行强制查询需要一段时间才能让我的计算机处理。提前感谢您的帮助。

TL; DR。我无法找出使用INNER / LEFT OUTER JOIN,EXISTS和UNION / INTERSECT / EXCEPT语句的有效方法来帮助我根据多个数据集隔离较小的数据集要求,以满足我需要交叉查询许多现有表而没有正确索引的外键。

1 个答案:

答案 0 :(得分:0)

内部联接是否所有必需的表格对您的需求来说太慢了?

您可以创建仅包含所需子集数据的表,然后对这些表运行内部联接。

所以创建一个表"电影"并仅插入" title"中的那些记录。与kind_id为1.然后执行类似

的操作
Select * 
FROM 
  movie m 
  inner join movie_info mi
    on m.id = mi.movie_id
  inner join complete_cast cc
    on m.id = cc.id
WHERE
  ...

如果您的新表格没有相同数量的数据,那么它应该会表现得更好。