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
Điều này ít nhất phải gần với những gì bạn yêu cầu. Việc chuyển nó thành một pivot sẽ yêu cầu SQL động vì SQL Server yêu cầu bạn chỉ định giá trị thực tế sẽ được pivot thành một cột.
Chúng tôi kết hợp chéo các câu hỏi và giới hạn kết quả từ mỗi tham chiếu câu hỏi đó thành một câu hỏi đơn lẻ cho các giá trị hàng và giá trị cột tương ứng. Sau đó, chúng tôi nối các giá trị tùy chọn vào tham chiếu câu hỏi tương ứng. Chúng tôi sử dụng LEFT JOIN cho các câu trả lời trong trường hợp người dùng không trả lời tất cả các câu hỏi. Và chúng tôi kết hợp các câu trả lời theo UserID để chúng tôi khớp câu hỏi hàng và câu hỏi cột cho mỗi người dùng. MIN trên văn bản tùy chọn là do chúng tôi đã nhóm và sắp xếp theo OptionID để khớp với trình tự của bạn được hiển thị.
CHỈNH SỬA:Đây là SQLFiddle
Đối với giá trị của nó, truy vấn của bạn phức tạp vì bạn đang sử dụng mẫu thiết kế Thực thể-Thuộc tính-Giá trị. Khá nhiều chuyên gia SQL Server coi mẫu đó là có vấn đề và cần tránh nếu có thể. Ví dụ:xem https:/ /www.simple-talk.com/sql/t-sql-programming/avoiding-the-eav-of-destruction/ .
CHỈNH SỬA 2:Vì bạn đã chấp nhận câu trả lời của tôi, đây là giải pháp xoay trục SQL động :) 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