2

1 対多の関係で 2 つのテーブル (件名とページ) があります。サブジェクトとページから基準を追加してSQLを解析したいのですが、進行が非常に遅く、しばしば問題が発生します。私はレールが初めてなので、助けてください。

class Subject < ActiveRecord::Base
  has_many :pages
end

class Page < ActiveRecord::Base
  belongs_to :subject 
end

被験者のサンプル データ。以下に 3 つの列を示します。

id  name    level
1   'Math'  1
6   'Math'  2
...

ページ内のサンプル データ。以下に列を示します。

id  name                    subject_id
--  --------------------    ----------
2   Addition                1
4   Subtraction             1
5   Simple Multiplication   6
6   Simple Division         6
7   Hard Multiplication     6
8   Hard Division           6
9   Elementary Divsion      1

subject.id がわからないので、件名とレベル、ページ名しかわかりません。これが私が生成したいSQLです(または同じ結果を達成する同様のもの):

select subjects.id, subjects.name, pages.id, pages.name from subjects, pages
 where subjects.id = pages.subject_id
   and subjects.name = 'Math'
   and subjects.level = '2'
   and pages.name like '%Division'  ;

結果に 2 つの行が表示されることを期待しています。

subjects.id     subjects.name   pages.id    pages.name 
-----------     -------------   --------    -----------
6               Math            6           Simple Division
6               Math            8           Hard Division

これは非常に単純な sql ですが、Rails で欲しいものを得ることができませんでした。

Here is my rails console:  

>> subject = Subject.where(:name => 'Math', :level => 2)
  Subject Load (0.4ms)  SELECT `subjects`.* FROM `subjects` WHERE `subjects`.`name` = 'Math' AND `subjects`.`level` = 2
[#<Subject id: 6, name: "Math", position: 1, visible: true, created_at: "2011-12-17 04:25:54", updated_at: "2011-12-17 04:25:54", level: 2>]
>> 
>> subject.joins(:pages).where(['pages.name LIKE ?', '%Division'])
  Subject Load (4.2ms)  SELECT `subjects`.* FROM `subjects` INNER JOIN `pages` ON `pages`.`subject_id` = `subjects`.`id` WHERE `subjects`.`name` = 'Math' AND `subjects`.`level` = 2 AND (pages.name LIKE '%Division')
[#<Subject id: 6, name: "Math", position: 1, visible: true, created_at: "2011-12-17 04:25:54", updated_at: "2011-12-17 04:25:54", level: 2>, #<Subject id: 6, name: "Math", position: 1, visible: true, created_at: "2011-12-17 04:25:54", updated_at: "2011-12-17 04:25:54", level: 2>]
>> 
>> subject.to_sql
"SELECT `subjects`.* FROM `subjects`  WHERE `subjects`.`name` = 'Math' AND `subjects`.`level` = 2"
>> subject.size
1
>> subject.class
ActiveRecord::Relation

1 つ目のステートメント: subject = Subject.where(:name => 'Math', :level => 2) 2 つ目のステートメント: subject.joins(:pages).where(['pages.name LIKE ?', '%Division'] )

質問:

  1. チェーン SQL の結果は実際には 2 行を返しますが、subject.size は 1 しか示していませんか?
  2. :pages からも列を返すようにするにはどうすればよいですか?
  3. subject.to_sql がまだステートメント 1 の SQL のみを表示するのはなぜですか? なぜステートメント 2 のチェーン SQL が含まれていないのですか?
  4. 基本的に、上記のように sql を解析する (または同じ結果を得る) には、ステートメントを別の方法で記述する必要がありますか?

どうもありがとう。

4

1 に答える 1

5

1) ActiveRecord は、クエリの結果を任意の返された行ではないオブジェクトSubjectにマップするため、クエリの作成をクラスに基づいているため、結果の行を見て、1 つの一意のSubjectオブジェクトのみを参照していることがわかるので、戻りますその単一のSubjectインスタンスだけです。

2) 列データはそこにありますが、ActiveRecord が提供したいもの、つまりオブジェクトに対して作業を行っています。Pages を返したい場合は、Pageクラスに基づいてクエリを作成する必要があります。

join(:pages)...3) back をsubject変数に追加した結果を保存しませんでした。あなたがした場合:

subject = subject.joins(:pages).where(['pages.name LIKE ?', '%Division'])

実行時に完全なクエリを取得しますsubject.to_sql

Page4) ページ オブジェクトを取得するには、次のようにします。クラスに基づいていることに注意してください。

pages = Page.joins(:subject).where(['subjects.name = ? AND subjects.level = ? AND pages.name LIKE ?', 'Math', 2, '%Division'])

次に、Page返された最初のオブジェクトのサブジェクト名にアクセスします。

pages[0].subject.name

最初に結合があるため、別の SQL クエリは発生しません。お役に立てれば!

于 2011-12-19T06:41:45.630 に答える