特定の製品の対象となるすべてのメンバーとその家族を基本的に検索するクエリがあります。同じファミリーに属していても、各ファミリー メンバーは個別の行に表示されます。注目のMySQLを使用しています。
例 (実際に返されたすべてのデータの小さなサンプル):
ID | familyid | firstname | lastname | address | city | relationship
==============================================================================
1 | 1 | john | davis | 942 James Ln | cityplace | primary
2 | 1 | suzy | davis | 942 James Ln | cityplace | spouse
3 | 2 | andrew | smith | 444 A Rd | new york | primary
4 | 3 | Mike | lewis | 123 Street | dallas | primary
5 | 3 | Donna | lewis | 123 Street | dallas | child
1 | 3 | Jamie | lewis | 123 Street | dallas | child
上の表の (作成された) データは、次の 2 つの表から取得されています。
- 一次情報 (メンバーと住所に関するすべての一般情報が含まれます)
- 家族情報(配偶者と子供の名前と性別情報を含む)
簡単にするために、これらのテーブルに含まれる情報は次のとおりであると仮定します。
メンバー
ID | familyid | firstname | lastname | address | city
-----------------------------------------------------
家族
ID | familyid | firstname | lastname | type | gender
------------------------------------------------------
私たちのシステムのメンバーは、選択した複数の製品を持つことができます (情報は別の表にあります)。残念ながら、上記のようなステートメントを構築する唯一の方法は、基本的に同じ情報を 2 回選択してから、次のサンプル ステートメントのように UNION ALL ステートメントを実行することです。
SELECT r.* FROM (
SELECT familyid, firstname, lastname, address, city, 'primary'
FROM member
UNION ALL
SELECT a.familyid, b.firstname, b.lastname, a.address, a.city, IF(b.type = 1, 'spouse', 'child')
FROM member a
JOIN family b ON (a.familyid = b.familyid)
) r
これはすでに少し混乱していますが、すでに収集されている「名前」情報に他のいくつかのテーブルを結合し始めると、「本当の」問題が発生します。たとえば、クエリ全体に結合ステートメントを追加して、HBO テレビ サービスを選択したメンバーまたは家族のみを表示できます。
after last statement: JOIN channels c ON (r.familyid = c.familyid)
これにより、以前に選択したステートメントで HBO を持っていないすべてのメンバーが除外されますが、HBO のサブセクション (メンバーのみのバージョンと家族全員のバージョンを持っている人など) を選択したい場合はどうなりますか? これらの後続のクエリでは、基本的にまったく同じ呼び出しを 2 回行う必要があり、わずかに異なる情報しか返されません。
SELECT r.* FROM (
SELECT familyid, firstname, lastname, address, city, 'primary'
FROM member m
JOIN channels c ON (m.familyid = c.familyid)
WHERE c.name = "HBO" and c.memtype = "member only"
UNION ALL
SELECT a.familyid, b.firstname, b.lastname, a.address, a.city, IF(b.type = 1, 'spouse', 'child')
FROM member a
JOIN family b ON (a.familyid = b.familyid)
JOIN channels c ON (b.familyid = c.familyid)
WHERE c.name = "HBO" and c.memtype = "family"
) r
これらのステートメントをより適切に最適化する方法はありますか? この件に関して、MySQL は単なる SOL ですか?
注: 表はそのまま正規化されているため、改善を提案しないでください。この特定のクエリは、1 か月に 1 回、必要に応じて (非常にまれに) 自動的に生成される 1 つのレポート用です。スキーマをそのまま使用して Union ステートメントを回避できるかどうかを調べようとしているだけです。スキーマは変更できません。