sql >> Databasteknik >  >> 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

Detta borde åtminstone vara nära det du bad om. Att förvandla detta till en pivot kommer att kräva dynamisk SQL eftersom SQL Server kräver att du anger det faktiska värdet som ska pivoteras till en kolumn.

Vi korsfogar frågorna och begränsar resultaten från var och en av dessa frågehänvisningar till den enskilda frågan för radvärden respektive kolumnvärden. Sedan sammanfogar vi alternativvärdena till respektive frågereferens. Vi använder LEFT JOIN för svaren om användaren inte svarade på alla frågorna. Och vi sammanfogar svaren genom UserID så att vi matchar radfrågan och kolumnfrågan för varje användare. MIN på alternativtexten beror på att vi grupperade och sorterade efter OptionID för att matcha din sekvensering som visas.

EDIT:Här är en SQLFiddle

För vad det är värt är din fråga komplicerad eftersom du använder designmönstret Entity-Attribute-Value. En hel del SQL Server-experter anser att det mönstret är problematiskt och bör undvikas om möjligt. Se till exempel https:/ /www.simple-talk.com/sql/t-sql-programming/avoiding-the-eav-of-destruction/ .

EDIT 2:Eftersom du accepterade mitt svar, här är den dynamiska SQL-pivotlösningen :) 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. Kan ett JOBB skapas dynamiskt i en trigger?

  2. MySQL swap primära nyckelvärden

  3. Hur får du reda på föråldrade funktioner i en ny version av Oracle?

  4. SQL Server - anslut med Windows-autentisering