Andrew Maughan
Andrew Maughan

Reputation: 25

SQL Joins across multiple tables

I am building an online survey system for which I wish to produce statistics. I want query based on the gender of the user. I have the following tables:

I have constructed the following query so that it brings back a null response where there are no answers to the question:

SELECT COUNT(sa.option_id) AS answer , so.option_label
FROM survey_answer sa 
RIGHT JOIN survey_question_options so 
        ON sa.option_id = so.option_id AND 
           sa.record_date>='2011-09-01' AND 
           sa.record_date<='2012-08-01'
LEFT JOIN users u 
       ON (sa.uid = u.uid AND u.gender='F')
WHERE so.question_id=24
GROUP BY so.option_label
ORDER BY so.option_id ASC

My query returns the following results set:

0 Red
1 Yellow
0 Blue
0 Green

However, the gender condition in the LEFT JOIN appears to be ignored in the query. When I change the gender to 'M' the same result is returned. However, the expected result would be 0 for everything.

I am not sure where I am going wrong. Please help.

Thanks in advance.

Upvotes: 0

Views: 411

Answers (3)

Naltharial
Naltharial

Reputation: 2152

You're putting your condition in the wrong block. Since you're performing a LEFT JOIN, (which is a left-bound outer join) everything in the left table (the main table) is selected, together with the data from the joined table, where applicable. What you want is to add the data from all users and then restrict the full output of the query. What you've actually done is add the user data from only the female users and then displayed all data.

Sounds technical, but all you have to do is move the AND u.gender='F' into the main WHERE clause instead the ON clause. That will cause SQL to only select the rows for female users after the JOIN has taken place.

Upvotes: 0

Lamak
Lamak

Reputation: 70638

Well, you are doing a COUNT on a column from the main table, so the gender condition on the LEFT JOIN won't affect the result. You should do the COUNT on a column from the users table. I'm not sure if this is what you want, but you should try:

SELECT COUNT(u.uid) AS answer , so.option_label
FROM survey_answer sa 
RIGHT JOIN survey_question_options so 
        ON sa.option_id = so.option_id AND 
           sa.record_date>='2011-09-01' AND 
           sa.record_date<='2012-08-01'
LEFT JOIN users u 
       ON (sa.uid = u.uid AND u.gender='M')
WHERE so.question_id=24
GROUP BY so.option_label
ORDER BY so.option_id ASC

Upvotes: 1

user359040
user359040

Reputation:

The left join to the users table is evaluated after the join to the answer table - so although the user record is not returned if the user is the wrong gender, the answer record will be returned (regardless of the user's gender). Try:

SELECT COUNT(sa.option_id) AS answer , so.option_label
FROM (select a.option_id
      from survey_answer a
      JOIN users u ON a.uid = u.uid AND u.gender='F'
      where a.record_date>='2011-09-01' AND 
            a.record_date<='2012-08-01') sa
RIGHT JOIN survey_question_options so 
        ON sa.option_id = so.option_id
WHERE so.question_id=24
GROUP BY so.option_label
ORDER BY so.option_id ASC

Upvotes: 0

Related Questions