我有一个使用 sqlite3 的数据记录应用程序来存储共享一个公共标头的不同类型的记录。
我将标题放在一个表中,并为每个变体的详细信息创建了单独的表。
明细表中的rowid就是表头的rowid。标题 rowid 仅显示在其中一个详细信息表中(对于该变体)。
我想在单个查询中获取多种类型的记录。也就是说,我希望 Sqlite 对 headers 表进行索引搜索以找到一组工作记录,然后使用该组 id 通过 rowid 快速二进制获取变体详细信息。所以:
SELECT * FROM headers JOIN headers
ON headers.id = variant1.id OR headers.id = variant2.id
WHERE some_header_condition
或者
SELECT * FROM headers JOIN headers
ON headers.id IN (variant1.id, revariant2.id )
WHERE some_header_condition
这可行,但是当遇到 JOIN 谓词中的 OR 项时,sqlite3 会对详细信息表 variant1 和 variant2 进行全表扫描,而不是仅通过 rowid 外键获取适当的记录。
就像是:
0 0 2 SCAN TABLE variant2 (~5900 rows)
0 1 1 SCAN TABLE variant1 (~26588 rows)
0 2 0 SEARCH TABLE headers USING INTEGER PRIMARY KEY (rowid=?) (~2 rows)
0 0 0 EXECUTE LIST SUBQUERY 1
我可以通过以下技巧强制二进制搜索:
SELECT header.f1, variant1.f, NULL FROM header JOIN header.id = variant1.id ...
UNION ALL
SELECT header.f1, NULL, variant2.f FROM header JOIN header.id = variant2.id ...
但随后头表被访问了两次。
我还可以想象将 header.id(s) 选择到一个临时表并使用它来使用其中的 id 获取详细信息。
或者......我可以将整个混乱状态反规范化。
但是所有这些变通方法都非常不方便。所以我的问题是,是否有一个不错的 JOIN 查询可以一次性获取这些变体而无需表扫描?