一般的なモデル: lords
have peons
、および bothlords
とpeons
have things
。は、1 つまたは複数のおよびthings
によって所有できます。領主が直接的または間接的に所有しているすべてを表示するには:peons
lords
things
SELECT lords.id AS lord_id,
peons.id AS peon_id,
things.id AS thing_id
FROM lords
LEFT JOIN lords_things ON
lords.id = lords_things.lord_id
LEFT JOIN peons ON
lords.id = peons.lord_id
LEFT JOIN peons_things ON
peons.id = peons_things.peon_id
JOIN things ON
lords_things.thing_id = things.id OR
peons_things.thing_id = things.id
WHERE lords.id = 123
現在、2 つの問題があります。
コードは、モノがどのレベルに接続されているかを判断するために
lord_id
、どちらpeon_id
が非であるかを調べる必要があります。NULL
これを解決する方法はたくさんあります。たとえば、Oracle では次のように言えます。SELECT NVL2(things_lords.id, 'lord', 'peon') as level
SQL Serverでは、次のように言うことができるはずです
SELECT CASE WHEN things_lords.id IS NULL THEN 'peon' ELSE 'lord' END AS level
しかし、私はこれらのどちらも (少なくとも PostgreSQL には) 移植可能ではないと思います。別のアプローチでは、次を使用し
UNION
ます。SELECT lords.id AS owner_id, 'lord' AS level, things.id AS thing_id FROM lords JOIN lords_things ON lords.id = lords_things.lord_id JOIN things ON lords_things.thing_id = things.id WHERE lords.id = 123 UNION SELECT peons.id AS owner_id, 'peon' AS type, things.id AS thing_id FROM lords JOIN peons ON lords.id = peons.lord_id JOIN peons_things ON peons.id = peons_things.peon_id JOIN things ON peons_things.thing_id = things.id WHERE lords.id = 123
ほとんどすべてのコードを複製するので、これは非常に醜いです。これのためのよりエレガントなポータブルソリューションはありますか?
things
複数回表示される場合もあります。これは私のアプリケーションの問題ではありませんが、完全を期すために言及されています。