5

languagesユーザーが望むだけ多くの言語を持つことができるテーブルでuser、このフィールドが集中的に検索されるため、シリアル化されたデータを使用しないことを願っています。

エントリ数を制限することを考えていました。たとえば、最大 4 言語で、ユーザー テーブルには lang1、lang2 ..

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

4

5 に答える 5

5

これはデータベースの正規化と呼ばれます。具体的には、 「多対多」の関連付けをマップする必要があります

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

編集:

@silkAdmin に注意する重要な点が 2 つあります。最初のものは、@ BryceAtNetwork23 が指摘したように、ID を User_Language テーブルに置く必要はありません。2 つ目は、 joins、特にMySQL Joinsについて学ぶ必要があるということです(SQL は DB エンジンごとに異なる傾向があるため)。もう少し掘り下げると、前のクエリで User テーブルを結合する必要がないことがわかります。これは次のように簡略化できます。

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を指定すると、言語を取得できます。欠点は、それを検索するのが本当に苦痛になることです。言語が「スペイン語」のすべてのユーザーをどのように取得しますか? (ここでの結論は、データにインデックスを付けることはできないということです)。もう 1 つの欠点は、ディスク領域の過剰使用です。DB と正規化が発明された当時、ディスク容量は非常に高価でした。したがって、これを保存します:

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

それは許せないことだった。それで、何人かの男が来て言った:「ねえ、IDを使ってみましょう。

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

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

10,000 人のユーザーと数百の言語の場合、これはディスク使用量の大幅な改善です (おそらく、現在では、これは当てはまりません。後で説明します)。これでディスクの問題は解決しましたが、検索の問題はまだ残っています。繰り返しますが、言語が「スペイン語」のすべてのユーザーをどのように取得しますか? さて、この設計では、users テーブルを反復処理して language 列を取得し、それを ";" で分割する必要があります。id 1 を探します。

そのため、以前お見せしたアプローチを使い始めました。

だから、これまでのところとても良いです。かなり良い説明;)

大きな免責事項

前述したように、これにはいくつかの方法があります。それはあなたのケースとあなたが何を達成したいかによって異なります。その列の観点から検索したい場合(たとえば、英語を話すユーザーを教えてください)、回答の上部で説明したデザインを検討する必要があります。

現在、データを非正規化しようとする、no-sql データベース (さまざま) と呼ばれるデータ ソリューションの「新しい波」があります。スキーマの過度の正規化が心配な場合は、それを確認する必要があります。MongoDB と CouchDB をお勧めします。これらのほうが始めやすいからです。

結合について

2 つの結合のパフォーマンスについて心配する必要はありません。パフォーマンスに問題がある場合は、このためではありません。DB エンジンは、この目的で作成されます。適切なメモリ キャッシュとインデックスの最適化により、スムーズに動作するはずです。

于 2012-04-06T17:33:10.837 に答える
1

はい、最良の方法は、追加のテーブルを使用して、列lang_idとを使用することuser_idです。そこには、任意の数のユーザー/言語の関連付け (行ごとに 1 つ) を格納できます。

于 2012-04-06T17:31:23.027 に答える
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)

このような制約により、ユーザーは必要な数の言語を割り当てることができます。

于 2012-04-06T17:32:13.057 に答える
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

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

于 2012-04-06T17:33:39.307 に答える
0

2 つのテーブルを持つことを検討する必要があると思います。1usersつと 1 つlanguagesjoinsこれらのテーブルは、保守が容易であり、実行も容易です。

于 2012-04-06T17:32:00.610 に答える