Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

SQL Cross Tab Query

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

Това трябва да е поне близо до това, което поискахте. Превръщането на това в пивот ще изисква динамичен SQL, тъй като SQL Server изисква да посочите действителната стойност, която ще бъде пивотирана в колона.

Свързваме кръстосано въпросите и ограничаваме резултатите от всяко от тези препратки към един въпрос съответно за стойностите на реда и стойностите на колоната. След това присъединяваме стойностите на опциите към съответната препратка към въпроса. Използваме LEFT JOIN за отговорите, в случай че потребителят не е отговорил на всички въпроси. И обединяваме отговорите по UserID, така че да съпоставим въпроса на реда и въпроса на колоната за всеки потребител. MIN в текста на опцията е, защото сме групирали и подредили по OptionID, за да съответства на показаната ви последователност.

РЕДАКТИРАНЕ:Ето SQLFiddle

Колкото и да си струва, вашата заявка е сложна, защото използвате шаблона за проектиране Entity-Attribute-Value. Доста експерти по SQL Server смятат този модел за проблематичен и трябва да се избягва, ако е възможно. Например вижте https:/ /www.simple-talk.com/sql/t-sql-programming/avoiding-the-eav-of-destruction/ .

РЕДАКТИРАНЕ 2:Тъй като приехте отговора ми, ето динамичното SQL pivot решение :) 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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server изпълнява резервно копие с C#

  2. Поточно предаване директно към база данни

  3. Използване на Dapper с SQL пространствени типове като параметър

  4. Обектът не може да бъде намерен, защото не съществува или нямате разрешения. Грешка в SQL Server

  5. Добавете водещи и последващи нули в SQL Server