2

users というタイトルの mySQL テーブルがあります。UID、評価、ユーザー名、パスワードなどがあります。

私の目標は、Facebook の友達リストに似たシステム (部族) を作ることです。各ユーザーは、ユーザーのプロフィールを表示して、部族に追加することができます。各ユーザーは 1 つの部族の首長ですが、必要な数の部族の村人になることができます。評価システムは、部族のすべてのメンバーの評価を考慮に入れます。

リレーショナル データベースのテーブルとグループ化について調査した結果、テーブルをどのようにセットアップすればよいか、またはそれに伴う PHP コードがよくわかりません。

誰かが私を正しい方向に向けることができれば、それは大歓迎です!

編集: 私が予見する大きな問題の 1 つは、部族であることを受け入れることです。あなたがこれをどのように説明しているのかわかりません。

4

2 に答える 2

2

Facebookの友達リストに似ています。各ユーザーは、ユーザーのプロフィールを表示して、部族に追加することができます。各ユーザーは、1 つの部族のみの首長です。

さて、あなたはUserテーブルを持っています、そしてまたテーブルが必要になりTribeます.

次に、あなたが説明している関係は ですchief-of、これは1対1です(1人のユーザーが1つの部族の首長になることができます; 1つの部族には1人の首長しかいません)、したがって、これをUser(chief_of: Tribe) またはTribe(チーフ: ユーザー)。

CREATE TABLE User ...
    chief_of integer

ここでchief_ofは、トライブを削除すると、関連するタプルがchief_ofNULL に設定されるように、外部キーである可能性があります (ユーザーは、存在しないトライブのチーフになることはできません)。

1 人のユーザーが複数の部族に属することができ、1 つの部族には複数のメンバーが存在するため、メンバーシップはもう少し複雑です。

これは多対多の関係であり、通常はキー ペアを保持するテーブルで行われます。

CREATE TABLE member_of (
    user_id integer,
    tribe_id integer
);

両方のフィールドは、外部キーの自然な候補です。ここでAuthorsは、 と を使用した同様の実装を見つけることができますBooks

Bob が Cave Bear のクランのメンバーであることを示すには、Bob と Bears の ID を取得し、タプルを に挿入しmember_ofます。

一族のすべてのメンバーを取得するには、JOIN を使用できます。

SELECT Users.* FROM Users
    JOIN member_of ON (Users.user_id = member_of.user_id)
    WHERE member_of.tribe_id =
        (SELECT tribe_id FROM Tribes WHERE tribe_name = 'Clan of the Cave Bear');

MySQL の ON の短いバージョンはUSING(user_id)(両方のテーブルに同じ名前の同じ列があることを意味します) だと思いますが、私の意見では、のON方が明確です。

仮想の「is_chief」列を取得することもできます。

SELECT Users.*, chief_of = tribe_id AS is_chief FROM Users
    JOIN member_of ON (Users.user_id = member_of.user_id)
    WHERE member_of.tribe_id =
        (SELECT tribe_id FROM Tribes WHERE tribe_name = 'Clan of the Cave Bear');

chief_of属性が部族 ID と等しい1 人のユーザーis_chiefは、1 に等しい TRUE に設定されているため、

SELECT Users.*, chief_of = tribe_id AS is_chief FROM Users
    JOIN member_of ON (Users.user_id = member_of.user_id)
    WHERE member_of.tribe_id =
        (SELECT tribe_id FROM Tribes WHERE tribe_name = 'Clan of the Cave Bear')
    ORDER BY (chief_of = tribe_id) DESC, user_name;

は、ユーザーをアルファベット順に取得します。ただし、チーフが存在する場合は最初になります。

トライブへの受け入れに関しては、これは 3 つの状態を識別します: ユーザーがトライブに参加していない、ユーザーがトライブに参加している、ユーザーがトライブに参加することを要求された。最初の 2 つは、実際には同じ属性の 2 つの面ですmember_of。したがって、当然、新しい属性を作成して、それを と呼びますwants_in。と同じテーブルにマップされmember_ofます。

チーフは、自分のタプルと等しいすべてのタプルwants_inを取得できます(したがって、それが NULL の場合、つまり彼がチーフではないことを意味する場合、これは自動的に何も返しません)。次に、これをユーザー名を含むチェックボックスの表として見ることができます。彼が結合を承認すると、承認ごとに からタプルを削除してに入れます。tribe_idchief_ofwants_inmember_of

または、「メンバーシップ」自体が状態であると判断して、より複雑な結合テーブルを作成することもできます。

user_id,
tribe_id,
status

statusたとえば、

  • なし ((U, T, ?) タプルがない): ユーザー U と部族 T はお互いに不明です
  • 100: ユーザー U は部族 T の正会員です
  • -1: 部族 T は、U がメンバーではなく、メンバーになることを要求することさえできないと判断しました。
  • 0: ユーザー U は T のメンバーになりたい
  • 1-99:ユーザーUは見習い(見習い)会員。
于 2013-05-03T06:23:22.197 に答える
2

Villagerとの 2 つのクラスが必要になるようですTribe

次に、おそらくデータベースフィールドchief_ofまたは何かと呼ばれnull、その人が首長ではない場合、その人が首長である部族の名前が含まれています。

クラスでgetChiefOf()は、ユーザーがチーフかどうかをテストできるメソッドを使用できます。


別の方法として、UID でインデックス付けされた首長のテーブルを作成し、同じ列に彼らがどの部族の首長であるかを示すこともできます。少し効率が悪いですが、より良い構造です。頭に浮かぶ欠点は、何らかの理由で UID が変更された場合、2 つのテーブルを更新する必要があるため、最初のテーブルの方が優れている可能性があることです。

于 2013-05-03T05:47:27.743 に答える