2011-07-26 6 views
1

私はmysqlの初心者です。ベストプラクティスを学びたいと思っています。私は以下のように同様の構造をセットアップしました。これはデータベースの正規化ですか?

(メイン、すべての一意のエントリを含むテーブル)TABLE = 'main_content'

+------------+---------------+------------------------------+-----------+ 
| content_id | (deleted) | title      | member_id | 
+------------+---------------+------------------------------+-----------+ 
|   6 |    | This is a very spe?cal t|_st |  1 | 
+------------+---------------+------------------------------+-----------+ 

は(各難易度の合計を提供し、ID加入 - >実際の名前)TABLE = '難しさ' を

+---------------+-------------------+------------------+ 
| difficulty_id | difficulty_name | difficulty_total | 
+---------------+-------------------+------------------+ 
|    1 | Absolute Beginner |    1 | 
|    2 | Beginner   |    1 | 
|    3 | Intermediate  |    0 | 
|    4 | Advanced   |    0 | 
|    5 | Expert   |    0 | 
+---------------+-------------------+------------------+ 

(このテーブルは、複数の値は、エントリごとに挿入することができることを確実にする。例えば、 この特定のエントリが2 dがあることを示し提出に関連したifficulties) TABLE =「lookup_difficulty」

+------------+---------------+ 
| content_id | difficulty_id | 
+------------+---------------+ 
|   6 |    1 | 
|   6 |    2 | 
+------------+---------------+ 

私が読める問合せにこのすべてに参加しています:

SELECT group_concat(difficulty.difficulty_name) as difficulty, member.member_name 
FROM main_content 
INNER JOIN difficulty ON difficulty.difficulty_id 
IN (SELECT difficulty_id FROM main_content, lookup_difficulty WHERE lookup_difficulty.content_id = main_content.content_id) 
INNER JOIN member ON member.member_id = main_content.member_id 

上記正常に動作しますが、私はこの場合は疑問に思って良い習慣です。私は実質的にWikipedia's Database Normalization exampleのレイアウトに従った。

EXPLAINを使用して上記のクエリを実行すると、次のように表示されます。私は2つの独立したサブクエリを使用しています。サブクエリを使用して同じ効果を達成する方法はありませんが、もう一度私はnoobですので、おそらくもっと良い方法があります。

+1

なぜ 'main_contant'困難にFKルックアップテーブルを持っていますか?ビルドしようとしていることを説明することができますので、デザインを評価することができますか? – Jacob

+0

lookup_difficultyテーブルを破棄して、代わりにmain_content(composite_id、difficult_id)の複合PKを使用するように見えます。 –

+0

申し訳ありませんが、私はその列を削除するつもりです。私はdifficult_idを使用していません..私は投稿を編集します。私はすべてのテーブルを本質的にmain_content.content_idに関連付けようとしています。 – Justin

答えて

1

lookup_difficultyにはcontentdifficultymain_contentテーブルからdifficulty_id列を取り出すことをお勧めします。各content_idに複数のルックアップを設定できるので、main_contentテーブルに入れるdifficulty_idテーブル(またはdifficulty_idテーブルの複数エントリ)を決定するためのビジネスロジックが必要になります。例えば、最大値/最小値/ランダム値。どちらの場合でも、あまり意味がありません。

表以外は正常です。


更新

あなただけのサイドノートとしてテーブル:)

を更新しました。 INを使用すると、クエリが遅くなる可能性があります(INがテーブルスキャンを引き起こす可能性があります)。いずれにせよ、それは以前のようなものでしたが、最近はSQLコンパイラがそれをかなりうまく最適化していると確信しています。 -

+0

ありがとうございました!参考として、mysqlが使用する典型的な速度はどこで調べることができますか?言い換えれば、あなたは「IN」が遅いことをどうやって見つけましたか? 'IN 'を' = ANY'に置き換えても同じ結果が得られます。私はどちらが速いのか分からず、 'EXPLAIN'はあまり洞察力を提供しません。 – Justin

+0

@Justin - 主に経験と読書から。 MySQLのクエリを分析できる独自のソフトウェアがあります。私が知っているオープンソース/フリーのものではありません(誰でも自由に例を挙げてください)。 –

+0

私はいつもプロファイラを使うことができたと思います。私は提出された各コンテンツの検索に多くの結合を使用するので、ある程度最適化されていることを確認することをお勧めします。 – Justin

2

DB設計が正常に見えるように参加して、あなたのクエリについて、あなたが独占的にそれを書き換えることができます:

SELECT group_concat(difficulty.difficulty_name) as difficulty, member.member_name 
     FROM main_content 
     INNER JOIN lookup_difficulty ON main_content.id = lookup_difficulty.content_id 
     INNER JOIN difficulty ON difficulty.id = lookup_difficulty.difficulty_id 
     INNER JOIN member ON member.member_id = main_content.member_id 
+0

優秀! 'ON difficult.id'に' ON difficult.difficulty_id'が代入されたときにうまく動作します。ありがとうございました!! 'EXPLAIN'を使用した後、すべてのSELECT_TYPESは単純であり、サブクエリはありません。これは私が探していたものです! – Justin

+0

あなたは大歓迎です、私は助けることができてうれしいです –

関連する問題