sql >> Databáze >  >> 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

Mělo by se to alespoň blížit tomu, co jste požadovali. Převedení tohoto na pivot bude vyžadovat dynamické SQL, protože SQL Server vyžaduje zadání skutečné hodnoty, která bude převedena do sloupce.

Křížově spojujeme otázky a omezujeme výsledky z každého z těchto odkazů na jednu otázku pro hodnoty řádků a hodnoty sloupců. Potom připojíme hodnoty možností k příslušnému odkazu na otázku. Pro odpovědi používáme LEFT JOIN v případě, že uživatel neodpověděl na všechny otázky. Odpovědi spojujeme podle ID uživatele, abychom pro každého uživatele porovnali otázku řádku a otázku sloupce. MIN v textu možnosti je způsobeno tím, že jsme seskupili a seřadili podle OptionID, aby odpovídalo vašemu zobrazenému pořadí.

EDIT:Zde je SQLFiddle

Za to, co stojí za to, je váš dotaz komplikovaný, protože používáte návrhový vzor Entita-Attribute-Value. Poměrně málo odborníků na SQL Server považuje tento vzor za problematický a je třeba se mu pokud možno vyhnout. Viz například https:/ /www.simple-talk.com/sql/t-sql-programming/avoiding-the-eav-of-destruction/ .

ÚPRAVA 2:Vzhledem k tomu, že jste přijali moji odpověď, zde je řešení dynamického pivotu SQL :) 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. #1067 - Neplatná výchozí hodnota pro 'bonusid' Jak mohu opravit tuto chybu?

  2. Django:Jaké jsou nejlepší postupy pro migraci projektu ze sqlite na PostgreSQL

  3. Rozdělte jeden sloupec na více řádků

  4. Pomocí FILE_NAME() vrátíte název logického souboru pro dané ID souboru na serveru SQL Server