はこれらのテーブルにあるMySQLのクエリを把握ヘルプそれら。テーブルにはOrderからSpeciesまでの階層構造があります。各テーブルには、階層上のそれ自身の上の直接テーブルに関連する外部キー(FK)があります。私は私が持っている
これを実現しようとしていますが、うまくやっていません。 ご協力いただければ幸いです!
はこれらのテーブルにあるMySQLのクエリを把握ヘルプそれら。テーブルにはOrderからSpeciesまでの階層構造があります。各テーブルには、階層上のそれ自身の上の直接テーブルに関連する外部キー(FK)があります。私は私が持っている
これを実現しようとしていますが、うまくやっていません。 ご協力いただければ幸いです!
これをすばやく汚れたショットにするだけで、このようなことを書くことができます。私は、MySQLの構文は少し異なる場合がありますので、火の鳥を使用して私の時間の大半を費やしていますが、属はその後、あなただけ削除されてそこに強制したい場合にアイデアが
select f.name
from family f left join genus g on f.id = g.family_id
left join species s on g.id = species.genus_id
where (s.id is null)
明確にする必要があり、「左」ファミリーから属への参加の一部。
私は質問を誤解していないと思いますので、間違った道を導いてくれることを願っています。がんばろう!
編集:実際には、これは私が属の中に種がない家族を捕まえてくれると思います。 "and(g.id is null)"を追加することもできます。
副SELECT救助に...
select f.name from family as f, genus as g
where
f.id == g.family_id and
g.id not in (select genus_id from species);
SELECT f.name
FROM family f
WHERE NOT EXISTS (
SELECT 1
FROM genus g
JOIN species s
ON g.id = s.genus_id
WHERE g.family_id = f.id
)
注意、純粋LEFT JOIN
ソリューションとは異なり、これは、より効率的であるより。
NOT NULL
の値を除外するすべての行を選択するのではなく、genus
とspecies
から最大で1行を選択します。
あなたと私は出産時に分かれていましたか? – tpdi
メタ答(前の2つの回答にコメント):
inを使用しては非常に、IN内のすべての用語のOR(論理和)のようなものに劣化する傾向があります。パフォーマンスが悪い
左結合を実行してnullを検索することは改善ですが、それは隠喩的です。我々は我々が何を意味するかと言うことができれば、我々は自然言語でそれを言うと思いますどのようにclossestだWAUでそれを言わせて:
select f.name
from family f left join genus g on f.id = g.family_id
WHERE NOT EXISTS (select * from species c where c.id = g.id);
何かが存在しない場合には我々がしたいので、私たちはどこ」と言うことができるかどうか存在していない "と言いました。そして、サブクエリ内のselect *
は実際に行全体を戻しているわけではないので、select *
をselect 1
に置き換える "最適化"ではなく、現代のRDBMSには少なくともありません。
さらに、家族が多くの属(生物学では、ほとんどの家族が行う)がある場合、私たちが気にするものが家族である場合、1つの行(家族、属)が得られます。したがって、1家族につき1行を取得しましょう:
select DISTINCT f.name
from family f left join genus g on f.id = g.family_id
WHERE NOT EXISTS (select * from species c where c.id = g.id);
これはまだ最適ではありません。どうして?それは「空」の属を見つける点でOPの要件を満たすが、それは一般的でない「空の」家族のない家族を見つけることができない。私たちもそれをすることができますか?
select f.name
from family f
WHERE NOT EXISTS (
select * from genus g
join species c on c.id = g.id
where g.id = f.id);
私たちは家族に何かに参加していないので、私たちは別のものを取り除くことさえできます。そのはです。 OPから
コメント:
非常に明快な説明でした。しかし、なぜ私はINまたはdisjunctionsを使用することがパフォーマンスに悪いのか不思議です。それについて詳しく説明したり、私がさまざまなDB操作の相対的なパフォーマンスコストについてもっと知ることができるリソースを教えてください。
このように考えてください。 SQLにIN演算子がないとします。どのようにINを偽造しますか? ORの一連
:
where foo in (1, 2, 3)
は
where (foo = 1) or (foo = 2) or (foo = 3)
に相当し[OK]を、あなたが言うが、それは悪いですなぜそれはまだ私に教えてくれありません。キーやインデックスを使用してこれを調べる方法がしばしばないため、悪いことです。ですから、あなたが得るのは、a)テーブルスキャンで、各論理和(またはINリストの要素)に対して、テストが真であるか、リストが使い果たされるまで、行がテストされます。または、b)これらの論理和のそれぞれに対して表スキャンを取得します。あなたは時々ORとの選択を参照してください理由である(b)は実際には良いかもしれ後者の場合は、一つになって、または一緒union'dの各脚を選択:
select * from table where x = 1 or x = 3 ;
select * from table where x = 1
union select * from table where x = 3 ;
を今、これは言っているわけではありませんORまたはINリストを決して使用することはできません。場合によっては、クエリオプティマイザはINリストを結合に変換するほどスマートであり、他の回答は、その可能性が最も高いケースです。
しかし、明示的にクエリを結合にすることができれば、クエリオプティマイザがスマートであるかどうか疑問に思う必要はありません。一般的に、ジョインとはデータベースがデータを処理するのに最適なものです。
これは非常に明快な説明でした。しかし、なぜ私はINまたはdisjunctionsを使用することがパフォーマンスに悪いのか不思議です。それについて詳しく説明したり、私がさまざまなDB操作の相対的なパフォーマンスコストについてもっと知ることができるリソースを教えてください。 – Calvin
[mysqlの分類表](http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/)これに関する素晴らしい記事。 [StackOverFlow](http://stackoverflow.com/questions/4048151/what-are-the-options-for-storing-hierarchical-data-in-a-relational-database) - what-are-the-options-for階層構造のリレーショナルデータベースのデータ – rd42