I have two tables, one that contains questions (that are considered ‘templates’):
|QuestionID|QuestionText |
|----------|------------------|
|1 |What is your name?|
|2 |What is your age? |
|-----------------------------|
And one that contains answers to those questions, keyed by a separate Customer ID value:
|CustID |QuestionID|Answer |
|----------|------------------|
|1000 |1 |John |
|1000 |2 |22 |
|2000 |1 |Alice |
|-----------------------------|
As you can see, Customer #1000 answered questions 1 and 2, and customer #2000 answered only question 1.
I need to load these into a grid on a web page by customer, and I thought I’d just do a left outer join between the template and answer tables to get something like this:
|CustID |QuestionID|Answer |
|----------|------------------|
|2000 |1 |Alice |
|2000 |2 |<null> |
|-----------------------------|
So in this case, cust #2000 would come back with the Answer column for question #2 as null and the application would know that it needs to be answered. This is an example of the SQL I tried but no matter how many combinations of OUTER and LEFT and so on I use for the JOIN, I just can’t get this to work with a single query:
select
q.QuestionID,
q.QuestionText,
a.CustID,
a.Answer,
from
SurveyAnswers a
full outer join SurveyQuestions q
on a.QuestionID = q.QuestionID
where
a.CustID = @CustomerID
Basically I need all the records in the SurveyQuestions table, and the value of the Answer column from any records in SurveyAnswers that match the CustomerID.
Instead I just get the one record in SurveyAnswers that has an answer, and therefore is a match (I guess?) in SurveyQuestions. My SQL-fu is not strong.
I also tried UNION and friends, but the two tables have different structures so that didn’t work too well.
I could of course pull the questions and answers separately and do the ‘coalescing’ in my C# code but I wanted to see if I could do it directly from the stored procedure. Thanks!
The problem you are having is that after an outer join on a mismatching row (Question 2 in your example) all columns for that row of the mismatched table (SurveyAnswers) are valued NULL. That includes the CustId column. The WHERE that executes later sees NULL = @CustomerId and excludes that row. To fix that you need to move the condition into the join clause. So you need to ask SQL Server for all questions together each’s answer given by “@CustomerId” if such answer exist. Your query is asking for (all questions and all their answers) but return only those records that “@CustomerId” answered.
should do the trick.