sqlite3 を使用して、共通のヘッダーを共有するさまざまな種類のレコードを保存するデータ ログ アプリがあります。
ヘッダーを 1 つの表にまとめ、各バリアントの詳細について個別の表を作成しました。
詳細テーブルの行 ID は、ヘッダー テーブルの行 ID です。ヘッダー行 ID は、(そのバリアントの) 詳細テーブルの 1 つにのみ表示されます。
1 回のクエリで複数の種類のレコードを取得したいと考えています。つまり、Sqlite でヘッダー テーブルのインデックス付き検索を実行して、作業中のレコード セットを見つけ、その 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 は行 ID 外部キーによって適切なレコードをフェッチするだけでなく、詳細テーブル variant1 および variant2 の完全なテーブル スキャンを実行します。
何かのようなもの:
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 ...
ただし、ヘッダー テーブルは 2 回アクセスされます。
また、header.id(s) を一時テーブルに選択し、それを使用して ID を使用して詳細を取得することも想像できます。
または...混乱全体を非正規化することもできます。
しかし、これらの回避策はすべて非常に不便です。私の質問は、これらのバリアントをテーブル スキャンなしで一度に取得できる素敵な JOIN クエリはありますか?