Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Zapytanie krzyżowe SQL

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

To powinno być przynajmniej zbliżone do tego, o co prosiłeś. Przekształcenie tego w oś obrotu będzie wymagało dynamicznego SQL, ponieważ SQL Server wymaga określenia rzeczywistej wartości, która zostanie przestawiona na kolumnę.

Łączymy krzyżowo pytania i ograniczamy wyniki z każdego z tych odwołań do pytania do pojedynczego pytania odpowiednio dla wartości wierszy i wartości kolumn. Następnie dołączamy wartości opcji do odpowiedniego odniesienia do pytania. Używamy LEFT JOIN dla odpowiedzi na wypadek, gdyby użytkownik nie odpowiedział na wszystkie pytania. I łączymy odpowiedzi według UserID, aby dopasować pytanie w wierszu i w kolumnie dla każdego użytkownika. MIN w tekście opcji wynika z tego, że pogrupowaliśmy i uporządkowaliśmy według OptionID, aby dopasować pokazaną sekwencję.

EDYCJA:Oto SQLFiddle

Co jest warte, zapytanie jest skomplikowane, ponieważ używasz wzorca projektowego Entity-Attribute-Value. Wielu ekspertów SQL Server uważa ten wzorzec za problematyczny i należy go unikać, jeśli to możliwe. Na przykład zobacz https:// /www.simple-talk.com/sql/t-sql-programming/avoiding-the-eav-of-destruction/ .

EDYCJA 2:Ponieważ zaakceptowałeś moją odpowiedź, oto rozwiązanie dynamicznego obrotu 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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tabela wartości funkcji a wartości skalarne Funkcja dla pojedynczej wartości zwracanej Wartość

  2. SQL Server:jak ograniczyć dostęp do zaszyfrowanej kolumny, nawet z dba?

  3. Serwer SQL 2008 wymuszający datę z dd/MM/rrrr na MM/dd/rrrr

  4. Błąd PHP podczas łączenia się z bazą danych MS SQL przy użyciu PDO_DBLIB

  5. czy istnieje sposób na podzielenie ciągu w sql?