Note that there are some explanatory texts on larger screens.

plurals
  1. POComplex subqueries in activerecord
    text
    copied!<p>I'm doing a rails app. I have to do a comparison engine a bit complex. I'm currently trying to do a prototype. My query can vary widely so i have to work with a lot of scopes, but that's not my problem.</p> <p>My query have to compare candidates. These candidates have answered some tests. These tests belongs to category. Theses tests have different max value, and i have to be able to compare candidates by categories.</p> <p>So i have to calculate a % of good answers. I have to be able to compare candidates in all possible use cases in one category. So, i have to be able to compare the average good answer rate for all this category. </p> <p>In a nutshell : I have to be able to use subqueries in order to compare some candidates. I have to be able to compare them for a test or a category. My problem is using a subquery able to return a good answer rate for all tests a candidats may have passed in a category.</p> <p>And I have to be able to use this subquery in an order_by or having clause.</p> <p>How can I construct this subquery ? I have no problem to handle complex conditional queries with some scopes. This has to be a real subquery, because I am working with 6 or 7 models here. </p> <p>I ask for an active record way, cause this must work with whatever database supported by rails.</p> <p>Excuse my poor English. </p> <p>Edit :</p> <p>An example is worth 1000 words so how could do something like this :</p> <pre><code>Sessiontest.find(Candidat.where(:firstname =&gt; 'toto')) </code></pre> <p>This example is stupid, ok. So, is it possible to do something like this ?</p> <p>Edit2 :</p> <p>I saw some posts about AREL. I wish to know if it is possible to do this without a third party plugin.</p> <p>Is it possible to do some sub queries in subqueries with arel? Because for example, my number of points per test, is the sum of the points of all his questions. (Sad, but I have to keep it). And I need this, so my subquery can calculate my good answers %. </p> <p>So you got the idea. That's something, which has to be really powerful, so I need something powerful, and not too much error prone.</p> <p>Edit3 : I made some progress, but I can't for a while post an answer.</p> <p>It seem possible to get this work without any plugin. I have some success in buildings some subqueries like this :</p> <pre><code> toto = Candidat.where(:lastname =&gt; Candidat.select(:lastname).where(:lastname =&gt; "ulysse").limit(1)) </code></pre> <p>The request :</p> <pre><code>Candidat Load (1.0ms)[0m SELECT "candidats".* FROM "candidats" WHERE "candidats"."lastname" IN (SELECT "candidats"."id" FROM "candidats" WHERE "candidats"."lastname" = 'ulysse' LIMIT 1 </code></pre> <p>This works and create a real subquery. I will try some more advanced experiences, in order to get the level I actually need.</p> <p>Just tried sub-subquery works wonder too.</p> <p>Edit 5 : </p> <p>I am trying some more advanced things, and there is a lot of things, i still don't understand. </p> <pre><code>- toto = Candidat.where("id = ? / ? ", Sessiontest.select(:id).where(:id =&gt; 6), Sessiontest.select(:id).where(:id =&gt; 2)) </code></pre> <p>This is just a stupid example in order to get an object with an id of 3. This code works, but not as i expected.</p> <p>See, the sql :</p> <pre><code>1m[35m (1.0ms)[0m SELECT COUNT("sessiontests"."id") FROM "sessiontests" WHERE "sessiontests"."id" = 6 [1m[36mSessiontest Load (0.0ms)[0m [1mSELECT id FROM "sessiontests" WHERE "sessiontests"."id" = 6[0m [1m[35m (1.0ms)[0m SELECT COUNT("sessiontests"."id") FROM "sessiontests" WHERE "sessiontests"."id" = 2 [1m[36mSessiontest Load (1.0ms)[0m [1mSELECT id FROM "sessiontests" WHERE "sessiontests"."id" = 2[0m [1m[35mCandidat Load (1.0ms)[0m SELECT "candidats".* FROM "candidats" WHERE (id = 6 / 2) </code></pre> <p>So, it does not use a subqueries. I tried with .to_sql. But it introduce my sql this way :</p> <pre><code>1m[36mCandidat Load (0.0ms)[0m [1mSELECT "candidats".* FROM "candidats" WHERE (id = 'SELECT id FROM "sessiontests" WHERE "sessiontests"."id" = 6' / 2 )[0m </code></pre> <p>So active record quoted the subreust for security purpose. this is closer to my wish, but not really what i want.</p> <p>This does not work </p> <pre><code>Candidat.where("id = (?) / ? ", Sessiontest.select(:id).where(:id =&gt; 6).to_sql, Sessiontest.select(:id).where(:id =&gt; 2)) </code></pre> <p>Quotes prevents the subquery to work.</p> <p>But this work :</p> <pre><code>Candidat.where("id = (" + Sessiontest.select(:id).where(:id =&gt; 6).to_sql + ") / (" + Sessiontest.select(:id).where(:id =&gt; 2).to_sql + ") ") [1m[36mCandidat Load (1.0ms)[0m [1mSELECT "candidats".* FROM "candidats" WHERE (id = (SELECT id FROM "sessiontests" WHERE "sessiontests"."id" = 6) / (SELECT id FROM "sessiontests" WHERE "sessiontests"."id" = 2) )[0m </code></pre> <p>But I find this ugly. I will try to get these subqueries working in a more dynamic way. I mean replace the integer values by columns name.</p>
 

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