SELECT MIN(ro.OptionText) RowOptionText, MIN(co.OptionText) RowOptionText, COUNT(ca.AnswerID) AnswerCount
FROM tblQuestions rq
CROSS JOIN tblQuestions cq
JOIN tblOptions ro ON rq.QuestionID = ro.QuestionID
JOIN tblOptions co ON cq.QuestionID = co.QuestionID
LEFT JOIN tblAnswers ra ON ra.OptionID = ro.OptionID
LEFT JOIN tblAnswers ca ON ca.OptionID = co.OptionID AND ca.UserID = ra.UserID
WHERE rq.questionText = 'Gender'
AND cq.questionText = 'How happy are you?'
GROUP BY ro.OptionID, co.OptionID
ORDER BY ro.OptionID, co.OptionID
To powinno być przynajmniej zbliżone do tego, o co prosiłeś. Przekształcenie tego w oś obrotu będzie wymagało dynamicznego SQL, ponieważ SQL Server wymaga określenia rzeczywistej wartości, która zostanie przestawiona na kolumnę.
Łączymy krzyżowo pytania i ograniczamy wyniki z każdego z tych odwołań do pytania do pojedynczego pytania odpowiednio dla wartości wierszy i wartości kolumn. Następnie dołączamy wartości opcji do odpowiedniego odniesienia do pytania. Używamy LEFT JOIN dla odpowiedzi na wypadek, gdyby użytkownik nie odpowiedział na wszystkie pytania. I łączymy odpowiedzi według UserID, aby dopasować pytanie w wierszu i w kolumnie dla każdego użytkownika. MIN w tekście opcji wynika z tego, że pogrupowaliśmy i uporządkowaliśmy według OptionID, aby dopasować pokazaną sekwencję.
EDYCJA:Oto SQLFiddle
Co jest warte, zapytanie jest skomplikowane, ponieważ używasz wzorca projektowego Entity-Attribute-Value. Wielu ekspertów SQL Server uważa ten wzorzec za problematyczny i należy go unikać, jeśli to możliwe. Na przykład zobacz https:// /www.simple-talk.com/sql/t-sql-programming/avoiding-the-eav-of-destruction/ .
EDYCJA 2:Ponieważ zaakceptowałeś moją odpowiedź, oto rozwiązanie dynamicznego obrotu SQL :) SQLFiddle
DECLARE @SqlCmd NVARCHAR(MAX)
SELECT @SqlCmd = N'SELECT RowOptionText, ' + STUFF(
(SELECT ', ' + QUOTENAME(o.OptionID) + ' AS ' + QUOTENAME(o.OptionText)
FROM tblOptions o
WHERE o.QuestionID = cq.QuestionID
FOR XML PATH ('')), 1, 2, '') + ', RowTotal AS [Row Total]
FROM (
SELECT ro.OptionID RowOptionID, ro.OptionText RowOptionText, co.OptionID ColOptionID,
ca.UserID, COUNT(ca.UserID) OVER (PARTITION BY ra.OptionID) AS RowTotal
FROM tblOptions ro
JOIN tblOptions co ON ro.QuestionID = ' + CAST(rq.QuestionID AS VARCHAR(10)) +
' AND co.QuestionID = ' + CAST(cq.QuestionID AS VARCHAR(10)) + '
LEFT JOIN tblAnswers ra ON ra.OptionID = ro.OptionID
LEFT JOIN tblAnswers ca ON ca.OptionID = co.OptionID AND ca.UserID = ra.UserID
UNION ALL
SELECT 999999, ''Column Total'' RowOptionText, co.OptionID ColOptionID,
ca.UserID, COUNT(ca.UserID) OVER () AS RowTotal
FROM tblOptions ro
JOIN tblOptions co ON ro.QuestionID = ' + CAST(rq.QuestionID AS VARCHAR(10)) +
' AND co.QuestionID = ' + CAST(cq.QuestionID AS VARCHAR(10)) + '
LEFT JOIN tblAnswers ra ON ra.OptionID = ro.OptionID
LEFT JOIN tblAnswers ca ON ca.OptionID = co.OptionID AND ca.UserID = ra.UserID
) t
PIVOT (COUNT(UserID) FOR ColOptionID IN (' + STUFF(
(SELECT ', ' + QUOTENAME(o.OptionID)
FROM tblOptions o
WHERE o.QuestionID = cq.QuestionID
FOR XML PATH ('')), 1, 2, '') + ')) p
ORDER BY RowOptionID'
FROM tblQuestions rq
CROSS JOIN tblQuestions cq
WHERE rq.questionText = 'Gender'
AND cq.questionText = 'How happy are you?'
EXEC sp_executesql @SqlCmd