Note that there are some explanatory texts on larger screens.

plurals
  1. PORails join with max condition
    primarykey
    data
    text
    <p>Given these two models</p> <pre><code>class Article &lt; AR::Base belongs_to :tag default_scope order('id DESC') end class Tag &lt; AR::Base has_many :articles scope :featured, order(:ordering).limit(5) end </code></pre> <p>I'm trying to join these two tables in a manner such I can retrieve a list of featured tags and for each of them the latest article in that tag with a single query, something like</p> <pre><code>Tag.featured.each do |tag| p tag.name p tag.articles.first.title # this will fetch the article in the tag with the highest id end </code></pre> <p>Written in this way this code has the <a href="http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations" rel="nofollow">(n+1) query problem</a>, I'm trying to optimize it because it will be run very frequently. I've excluded an <code>includes</code> call in the <code>featured</code> scope because it will load all the <code>Article</code> in the first 5 tags (a lot of articles...)</p> <p>In plain old SQL I can join this two tables using a query like this</p> <pre><code>SELECT tag_id, MAX(id) FROM articles GROUP BY tag_id # or in Rails Article.select('MAX(id), tag_id').group(:tag_id) +--------+---------+ | tag_id | MAX(id) | +--------+---------+ | 14 | 26787 | ... | 1 | 27854 | | 5 | 27780 | | 0 | 10953 | +--------+---------+ </code></pre> <p>as a join table I can retrieve all the data with a single query.</p> <p>How to port that in Rails and ActiveRecord?</p> <p><strong>update</strong></p> <p>The full query i need executed in AR context is</p> <pre><code>SELECT a.*, t.* FROM tags t JOIN (SELECT MAX(id) AS latest, tag_id FROM articles GROUP BY tag_id) j ON j.tag_id = t.id JOIN articles p ON j.latest = a.id LIMIT 5 </code></pre> <p>I tried <code>AR#find_by_sql</code> method with the latest query, I get the correct resultset but then I cannot navigate through objects</p> <pre><code>sql = '...' # This holds the previous query Tag.find_by_sql(sql).first.class =&gt; "Tag" Tag.find_by_sql(sql).first.articles.first =&gt; nil # why??? </code></pre> <p><strong>update 2</strong></p> <p>Tried also with </p> <pre><code>Tag.joins('JOIN ... all my query join part here ...').first.articles.first =&gt; nil </code></pre> <p>However I noticed that I can use my articles field directly as Tag fields, i.e. I can write</p> <pre><code>Tag.find_by_sql(...).first.title # where title is a field of Article class Tag.joins(...).first.title # where title is a field of Article class </code></pre> <p>but obviously I can not call <code>Article</code> instance methods.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload