0

私のユーザーモデルには、次のスコープがあります。

scope :with_tournament_entrees, :include => :registers, :conditions => "registers.id IS NOT NULL"

このスコープによってSQLが生成されるのを見たかったのですが、次のように生成されます。

"SELECT \"users\".* FROM \"users\"  WHERE (registers.id IS NOT NULL)"

追加したincludeパラメーターについての言及がなく、の助けを借りて生のSQLとしてコンソールで実行するとエラーが返されますActiveRecord::Base.connection.execute。一方、コンソールでUser.with_tournament_entreesをクエリすると、エラーなしで必要な正しい8つのレコードが生成されます。ログを見ると、SQLステートメントが実行されていることがわかります...

SELECT "users"."id" AS t0_r0, "users"."email" AS t0_r1, 
       "users"."encrypted_password" AS t0_r2, ....
       "registers"."id" AS t1_r0, "registers"."competition_id" AS t1_r1,
       "registers"."user_id" AS t1_r2 ... 
       FROM "users" LEFT OUTER JOIN "registers" ON "registers"."user_id" = "users"."id"
       WHERE (registers.id IS NOT NULL)

これはほぼ正しいように見えるので、SQLをコピーして内部にラップするActiveRecord::Base.connection.executeと、完全に実行されます。ただし、スコープを呼び出したときのように8レコードを取得する代わりに、 12レコードを取得します。

何が得られますか?まったく同じSQLを実行していますよね?では、なぜ私は異なる結果を得るのですか?PostgreSQLデータベースを使用しています。

ああ、私はあなたがRails 3でスコープを使うべきではないことを知っています、それが私がSQLを取得しようとしている理由です。

4

1 に答える 1

1

これは、2つの事実によって説明されます。1。結合を効果的に追加すると、ユーザー行とレジスタ行の有効な組み合わせごとに結果セット行を取得できます。したがって、一部のユーザーがレジスタテーブルに2つのレコードを持っている場合、そのユーザーレコードに対して2つの行を取得します。2. Active Recordは上記を認識しており、行を「マージ」できるため、それぞれ1つのレジスタを持つ2つの同じユーザーではなく、2つのレジスタを持つ1つのユーザーを取得できます。

このように、ベアクエリを実行すると、MySQLの観点から12行の結果が得られます。また、ActiveRecordはそれらを8レコードまで処理します。これは、一部の行に同じユーザーのフィールドが含まれているため、複数のレジスターのフィールドのみが含まれているためです。

お役に立てれば :)

于 2012-11-09T02:00:27.833 に答える