Reputation: 35
Let's say that I have two ActiveRecord models (or two tables in an SQL database, if you'd like). I have a User
class and a Poll
class. A User
has_many Polls
. When a user takes a Poll
, they are asked whether or not they like apples
, bananas
, and cherries
. The User
's response to each of these things is recorded in a boolean column.
I'm interested in finding out which users have taken Polls
and have responded that they like each of apples
, bananas
, and cherries
at ANY time (not necessarily at the same time). Put differently, they do not need to have said that they like all three fruits during one Poll
, they just need to have said that they like each of these things at some point, i.e. they need to have said that they like apples
in at least one Poll
, bananas
in at least one Poll
, and cherries
in at least one Poll
.
What's the right way to go about doing this in a general manner? Either an ActiveRecord or SQL query would be helpful.
Upvotes: 1
Views: 308
Reputation: 381
Or perhaps your table looks like this http://sqlfiddle.com/#!15/c0967/10:
create table polls (userid char(10), pollid char(10), questionid char(10), response boolean);
insert into polls (userid, pollid, questionid, response)
values ('1','1','APPLES',true),
('1','1','BANANAS',false),
('1','1','CHERRIES',true),
('1','2','APPLES',false),
('1','2','BANANAS',false),
('1','2','CHERRIES',true),
('1','3','APPLES',false),
('1','3','BANANAS',true),
('1','3','CHERRIES',true),
('2','1','APPLES',false),
('2','1','BANANAS',false),
('2','1','CHERRIES',true),
('2','2','APPLES',false),
('2','2','BANANAS',true),
('2','2','CHERRIES',true),
('2','3','APPLES',false),
('2','3','BANANAS',false),
('2','3','CHERRIES',true),
('3','1','APPLES',true),
('3','1','BANANAS',false),
('3','1','CHERRIES',false),
('3','2','APPLES',false),
('3','2','BANANAS',true),
('3','2','CHERRIES',false),
('3','3','APPLES',false),
('3','3','BANANAS',false),
('3','3','CHERRIES',true),
('4','1','APPLES',false),
('4','1','BANANAS',false),
('4','1','CHERRIES',false),
('4','2','APPLES',true),
('4','2','BANANAS',true),
('4','2','CHERRIES',true),
('4','3','APPLES',false),
('4','3','BANANAS',false),
('4','3','CHERRIES',false)
;
in which case you can create a temporary view grouping the user questions with true responses, and then count the records in that view like this:
with counts as (
select userid, questionid
from polls
where response = true
and questionid in ('APPLES','BANANAS','CHERRIES')
group by userid, questionid
)
select userid
from counts
group by userid
having count(*) = 3
Upvotes: 1
Reputation: 4310
Lets suppose your polls
table has boolean columns apples
, bananas
, and cherries
. Then for each user, you want to look at the corresponding polls and compute an aggregate OR function on each fruit column, keeping only the rows that return true for each fruit.
User.joins(:polls)
.group('users.id')
.having('BOOL_OR(polls.apples) = ? AND BOOL_OR(polls.bananas) = ? AND BOOL_OR(polls.cherries) = ?', true, true, true)
Upvotes: 2