sql >> Database teknologi >  >> 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

Dette burde i det mindste være tæt på det, du bad om. At omdanne dette til en pivot vil kræve dynamisk SQL, da SQL Server kræver, at du angiver den faktiske værdi, der vil blive pivoteret til en kolonne.

Vi krydser spørgsmålene og begrænser resultaterne fra hver af disse spørgsmålsreferencer til det enkelte spørgsmål for henholdsvis rækkeværdierne og kolonneværdierne. Derefter forbinder vi indstillingsværdierne til den respektive spørgsmålsreference. Vi bruger LEFT JOIN til svarene, hvis brugeren ikke svarede på alle spørgsmålene. Og vi samler svarene efter UserID, så vi matcher rækkespørgsmålet og kolonnespørgsmålet for hver bruger. MIN på indstillingsteksten skyldes, at vi grupperede og sorterede efter OptionID for at matche din viste sekvensering.

EDIT:Her er en SQLFiddle

For hvad det er værd, er din forespørgsel kompliceret, fordi du bruger designmønsteret Entity-Attribute-Value. En hel del SQL Server-eksperter anser dette mønster for at være problematisk og bør undgås, hvis det er muligt. Se for eksempel https:/ /www.simple-talk.com/sql/t-sql-programming/avoiding-the-eav-of-destruction/ .

EDIT 2:Siden du accepterede mit svar, her er den dynamiske SQL-pivotløsning :) 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. Sammenføj flere rækker i én kolonne ved hjælp af en funktion i Oracle med 3 relaterede tabeller

  2. Webinar:Nye funktioner i PostgreSQL 11 [Opfølgning]

  3. Dødlås ved forespørgsel efter INFORMATION_SCHEMA

  4. PostgreSQL - DISTINCT ON og GROUP BY syntaks