2012-04-06 20 views
4

languagesuserテーブルに入れておきたいときは、どうすればいいのでしょうか?うまくいけばこのフィールドは直列化されたデータを使用せずに集中的に検索されます。 Mysqlテーブルに任意の数の値を格納する最良の方法

exempleは4言語をする最大の、ユーザーテーブルにlang1、lang2を持っているため、私は、エントリ数をlimtating考えていた。..

は、これを達成するためのより良い方法はありますか?

答えて

4

database normalizationと呼ばれています。具体的にはマップする必要があります"Many to Many" association

3つのテーブルが必要です。

User(id, name) 
Language (id, language_name) 
User_Language(id,id_user,id_language) 

ユーザーID 3の全ての言語を取得するには:

SELECT l.language_name 
FROM User u 
JOIN user_language ul ON (u.id=ul.id_user) 
JOIN Language l ON (l.id = ul.id_language) 
WHERE u.id = 3 

EDIT:

2つのことは@silkAdminに気づくことが重要です。最初のものは、@ BryceAtNetwork23のように、User_LanguageテーブルにIDを入れる必要はありません。第二に、joins、特にMySQL Joinsについて学ぶべきです(異なるDBエンジンでSQLが異なる傾向があるため)。

SELECT l.language_name 
FROM user_language ul 
JOIN Language l ON (l.id = ul.id_language) 
WHERE ul.user_id = 3 

しかし、私は作るために最初の答えにこれを追加しました:あなたは、あなたのように単純化することができることを、以前のクエリでのユーザーテーブルに参加することも必要とされていないことを確認することができますもう少し掘り下げた後、物事はあなたに簡単です。

は、言語テーブル

を使用して、なぜ私の答えはちょうど私がそれを行うだろう道を反映しています。何を求めているかを練り上げる方法はたくさんあります。それは、私は自分自身を説明すると述べた。

極端に考えてみましょう。最初の極端なのは、上記のように言語をユーザーテーブルに格納することです。たとえば、列を持ち、値をセミコロンで区切ることができます。このようなもの

User: (1, "John", "spanish;english;japanese") 

この利点は、参加する必要がないことです。ユーザーのIDを指定すると、言語を取得できます。欠点は、それを検索することは本当に痛いということです。言語「スペイン語」を使用するすべてのユーザーをどのように獲得できますか? (ここの一番下の行は、データのインデックスを作成できないということです)。もう古い欠点は、ディスク領域の過剰使用です。 DBと正規化が発明された時、ディスクスペースは本当に高価でした。したがって、これを保存する:

User: (1, "John", "spanish;english;japanese") 
User: (2, "Mary", "spanish;english") 

これは容認できないものでした。 「我々はにそれを回すことができ、ねえ、のIDを使用してみましょう、そう」::だから、いくつかの男が来たと言う10.000ユーザーと言語のわずか数百のために

User: (1, "John", "1;2;3") 
User: (2, "Mary", "1;2") 

Language (1,"spanish") 
Language (2,"english") 

、それは、(ディスク使用量に大きな改善です多分私たちの時代には、これはもう真実ではなく、私は後でそれに行くでしょう)。それはディスクの問題を解決しましたが、私たちはまだ検索の問題があります。ここでも、「スペイン語」の言語を使用するすべてのユーザーを取得するにはどうすればよいですか?さて、この設計では、ユーザーテーブルを繰り返し、言語列を取得し、 ";" id 1を探してください。

私が以前に示したアプローチを使い始めたのはそのためです。

だから、これほど良い。説明かなり良い;)

ビッグ免責事項

私が前に言ったように、これを行うには、いくつかの方法があります。それはあなたの事件に依存し、あなたは何をしたいのですか。その列の観点から検索したい場合(私に英語を話すユーザーを与えるなど)、私はあなたが私の答えの先頭に言ったデザインを考慮する必要があります。

現在、データを非正規化しようとする、no-sqlデータベースと呼ばれる(変化する)データソリューションの「新しい波」があります。あなたがスキーマの過度の正規化を心配しているなら、それを見てください。私はMongoDBとCouchDBをお勧めします。

は約2のジョインのパフォーマンスを心配しないでください

に参加します。パフォーマンスの問題がある場合は、これは問題ではありません。この目的でDBエンジンが作成されます。良いメモリキャッシュとインデックスの最適化により、スムーズに動作するはずです。

+0

実際、USER_LANGUAGEにはIDフィールドは必要ありません。 id_userとid_languageのフィールド(連結キーとして)は、一意性を保証します。 – Aaron

+0

ええ、それは良い習慣です。私はその参加のユーザテーブルを必要としませんが、説明のために私はそれを追加しました。 – santiagobasulto

+0

@santiagobasulto詳細な回答ありがとうございます。私は結合を使用する方法を知っていますが、パフォーマンスを念頭に置いて、他の方法がない場合にのみ使用しようとします。なぜ私は言語表を使用するのが好奇妙ですが?ユーザー言語テーブルで十分である(id_languageを列挙型フィールドに置き換える) – silkAdmin

1

はい、最善の方法は、カラムがlang_iduser_idの追加テーブルを使用することです。ここには、任意の数のユーザー/言語の関連付け(行ごとに1つ)を格納できます。

0

私はあなたが2つのテーブルを持つことを検討すべきだと思います。 1つはusers、もう1つはlanguagesです。メンテナンスが容易で、joinsをこれらのテーブルに追加する方が簡単です。

1

作成テーブルuser_languages制約と

user_id int, 
language_id int, 

:あなたが望むような制約のある

PRIMARY KEY (user_id, language_id), 
FOREIGN KEY (language_id) REFERENCES language(id), 
FOREIGN KEY (user_id) REFERENCES users(id) 

は、ユーザーが多くの言語として割り当てられていることができます。

1

これを実現する最も良い方法は、USER表、USER_LANGUAGES表、およびLANGUAGES表を持つことです。このようにして、ユーザーは必要なだけ多くの言語を使用できます。

USER 
user_id int 
user_name varchar 

USER_LANGUAGES 
user_id int 
lang_id int 

LANGUAGES 
lang_id int 
lang_name varchar 

ユーザーは、ユーザーベースのフィールドを格納します。 LANGUAGESは、特定の言語(英語、ドイツ語など)ごとにデータを格納します。 USER_LANGUAGESは、どの言語をどのユーザーが知っているかの関連付けを格納します。

関連する問題