2

私はこの問題を抱えています:

  • ユーザーはキャンディーをたくさん持っています ( 1:M )。
  • キャンディーの 1 つにプライマリフラグを設定できます
  • ユーザーごとに 1 つのキャンディーのみをプライマリにすることができます

プライマリフラグを実行するためのより良い解決策はどれですか?

ソリューション1:

ユーザー

| id  | name |
| 1   | Joe  |

キャンディーズ

| id | user_id | primary |
| 1  |  1      | true    |  
| 2  |  2      | false   |

ソリューション 2:

ユーザー

| id  | name | primary_candy_id |
| 1   | Joe  | 2                |

キャンディーズ

| id | user_id |
| 1  |  1      |
| 2  |  2      |

ソリューション 1 のメモ

  • キャンディーテーブルのキャンディーに関連するすべてのものを手に入れました
  • キャンディーがプライマリかどうかを確認すると、クエリが高速になります(参加する必要はありません)
  • ユーザーが 100 個のキャンディーを取得した場合、この方法で 99 個がになり、意味のあるが 1 個だけになります=> 99 個の不要な列レコード

解決策 2 のメモ

  • このようにして、列レコードが 1 つだけになります (他に 99 を節約できます)。
  • Candy がプライマリかどうかを確認したい場合は、クライアント テーブルに参加する必要があります
  • ユーザーに関連するプライマリ フラグを持つ 1:M テーブルをさらに導入するとします: アイスクリーム、チョコレート、ジャンクフード... このようにして、ユーザーにさらに 4 つの列ができます。

これはよりSQLの問題ですが、プロジェクトでRails 3.*を使用しているため、この分野のベストプラクティスの意見を歓迎します

4

3 に答える 3

1

またはそのようなものと呼ばれる 3 番目のモデルを作成しUserCandy、データベース テーブルを次のようにします。

# users
| id | name |
| 1  | Joe  |

# candies
| id | name    |
| 1  | foo bar |

# user_candies
| id | user_id | candy_id |
| 1  | 1       | 1        |

# primary_candies
| id | user_candy_id |
| 1  | 1             |

次に、ユーザーとキャンディーの間に多対多の関係を設定します<insert some special type of candy here>

class User < ActiveRecord::Base
  has_many :user_candies
  has_many :candies, :through => :user_candies

  def primary_candy
    Candy.primary_for(self).first
  end
end

class Candy < ActiveRecord::Base
  has_many :user_candies
  has_many :users, :through => :user_candies

  scope :primary, joins(:user_candies => [:primary_user_candy, :user])
  scope :primary_for, lambda {|user| primary.where('users.id' => user.id) }
end

class UserCandy < ActiveRecord::Base
  belongs_to :user
  belongs_to :candy
  has_one :primary_candy
end

class PrimaryCandy < ActiveRecord::Base
  belongs_to :user_candy

  validate do
    if user_candy.user.primary_candy
      errors.add(:base, "User already has a primary  candy")
    end
  end
end

このようにすると、さまざまな種類のスナックを追加するときに users テーブルに列を追加する必要がなくなります。また、ユーザーが好きなキャンディーを持っている場合と持っていない場合があるため、この方法で users テーブルの null フィールドを回避できます。 .

この方法で、さまざまな種類のキャンディーを再利用することもできます。

したがって、リレーショナル データベースの観点からの私の簡単な答えは、次のようになります。フラグはありません。プライマリ キャンディーを別のモデルに配置します。

つまり、3 つのテーブル バージョンを使用して、user_candies テーブルにプライマリ フラグを配置することもできます。

上記のモデル コードを使用してサンプル Rails プロジェクトを作成しました。ここから入手できます。

于 2012-07-20T13:27:33.193 に答える
0

has_one アソシエーションはどうですか。そうすれば、両方の不要な列を削除し、必要なときにのみ User.primary_candy に簡単にアクセスできます。

User :has_many candy
User :has_one candy :through => primary_candy 

Candy :belongs_to user
Candy :has_many primary_candy

Primary_candy :belongs_to User
Primary_candy :belongs_to Candy
Primary_candy :validates_uniqueness_of :user_id, :scope => :candy_id

user.primary_candy.candy は、関連するキャンディーを返します。user.candy は、すべてのキャンディーのセットを返します。

candy モデルにメソッドを作成して、primary_candy をチェックし、そのレコードのみを .find することもできます。

def p_candy(user)
  p_candy_id = Primary_candy.find_by_user_id(user.id).candy_id
  p_candy = Candy.find(p_candy_id)
  return p_candy
end

また、さまざまな一次キャンディーの相対的な人気を簡単に確認できます。ちょっと、GL。

于 2012-07-20T13:28:35.277 に答える
0

存在しない 1 対多の関係に対して不必要なリンク テーブルを作成することで、これを不必要に複雑にしているように私には思えます。MyFavoriteColor は「私」(「お気に入り」) のモナド属性なので、単純に次のようにします。

      Tables:
         PEOPLE
         COLORS

People.FavoriteColor 列には COLORS テーブルのキーが含まれている必要があります。

       ALTER TABLE PEOPLE ADD CONSTRAINT FK_PEOPLE_COLOR
       foreign key(FavoriteColor) REFERENCES COLOR(id)

さて、衣料品店を経営していて、商品の色 (赤いシャツ、青いシャツ、緑のシャツ) を追跡したいとします。この場合、1 対多のリレーションシップ リンク テーブルが必要になる理由は次のとおりです。

       Tables:
           APPAREL
           COLORS
           APPARELCOLORS

       T-Shirt is an item in the APPAREL table
       Red, green, blue, white, etc are items in the COLORS table


        And then you'd have this in the APPARELCOLORS linkage table:


             Apparel | Color
             t-shirt | red
             t-shirt | blue
             hat   | white
             hat | black
             hat | yellow

「お気に入り」ルール (つまり、エンティティに関連付けられた複数の値のうちの 1 つだけが「お気に入り」列を True に設定できる) は、宣言的に強制することはできません。ルールを宣言的に適用する方法を常に見つけようとする必要があります。できるときは、優れたデザインを持っていることがわかります。

于 2012-07-20T16:59:53.113 に答える