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
Ini harus setidaknya mendekati apa yang Anda minta. Mengubahnya menjadi pivot akan membutuhkan SQL dinamis karena SQL Server mengharuskan Anda menentukan nilai aktual yang akan diputar menjadi kolom.
Kami menggabungkan pertanyaan silang dan membatasi hasil dari masing-masing referensi pertanyaan tersebut ke pertanyaan tunggal untuk nilai baris dan nilai kolom masing-masing. Kemudian kami menggabungkan nilai opsi ke referensi pertanyaan masing-masing. Kami menggunakan LEFT JOIN untuk jawaban jika pengguna tidak menanggapi semua pertanyaan. Dan kami menggabungkan jawaban dengan UserID sehingga kami mencocokkan pertanyaan baris dan kolom pertanyaan untuk setiap pengguna. MIN pada teks opsi adalah karena kami mengelompokkan dan mengurutkan berdasarkan ID Opsi agar sesuai dengan urutan yang ditampilkan.
EDIT:Inilah SQLFiddle
Untuk apa nilainya, kueri Anda rumit karena Anda menggunakan pola desain Entity-Attribute-Value. Beberapa ahli SQL Server menganggap pola itu bermasalah dan harus dihindari jika memungkinkan. Misalnya lihat https:// /www.simple-talk.com/sql/t-sql-programming/avoiding-the-eav-of-destruction/ .
EDIT 2:Karena Anda menerima jawaban saya, inilah solusi pivot SQL dinamis :) 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