2010-12-10 16 views
1

Ich habe eine Tabelle mit Spalten wie dieser SubjectID UserID. Es gibt viele subjectIDs für einen einzelnen Benutzer. Ich muss irgendwie auswählen, um ein ähnliches Ergebnis zu erhalten:Auswahl aus einer flachen Tabelle

UserID1 SubjectID1 SubjectID2 Subject3 
UserID2 SubjectID1 SubjectID2 Subject3 
UserID3 SubjectID1 SubjectID2 Subject3 
+0

@ p.campbell, ich vermute, dass er mit seinem ersten Satz tat .. –

Antwort

1

Zum Zwecke der Diskussion, lassen Sie uns ein Beispieldatensatz in einer Tabelle SubjectUser wie folgt genannt definieren:

;WITH 
    orderedSubjects AS (
    SELECT 
     UserId 
    , SubjectId 
    , 'SubjectId' 
     + CAST(
      ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY SubjectId) 
      AS NVARCHAR) 
     AS col 
    FROM SubjectUser 
) 
SELECT * 
FROM orderedSubjects 
PIVOT (
    MAX(SubjectId) 
    FOR col IN (SubjectId1, SubjectId2, SubjectId3) 
) AS p 
:

SELECT NULL AS SubjectId, NULL AS UserID INTO SubjectUser WHERE 1=0 
UNION SELECT 'cpsc500', 'maxt3r' 
UNION SELECT 'phil507', 'zontar33' 
UNION SELECT 'phil507', 'maxt3r' 
UNION SELECT 'eng501', 'zontar33' 
UNION SELECT 'eng501', 'maxt3r' 
UNION SELECT 'bkwv101', 'spaced99' 

Sie dann kann das gewünschte Ergebnis mit dieser Abfrage erhalten

Schauen wir uns diese Abfrage in Teilen an. Das erste Problem besteht darin, den Fächern jedes Benutzers Spaltennamen zuzuweisen. Die orderedSubjects Tabelle dient diesem Zweck, durch diese Abfrage definiert:

SELECT 
    UserId 
, SubjectId 
, 'SubjectId' 
    + CAST(
     ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY SubjectId) 
     AS NVARCHAR) 
    AS col 
FROM SubjectUser 

ROW_NUMBER() ... PARTITION BY ... ORDER BY verwendet, um eine Sequenznummer zu jedem Benutzer-Subjekten zugeordnet werden. Beliebig sind die Themen alphabetisch geordnet. Dann wird ein Spaltenname erzeugt, indem jeder Sequenznummer der String SubjectId vorangestellt wird. Das Ergebnis ist wie folgt:

UserId  SubjectId col 
maxt3r  cpsc500  SubjectId1 
maxt3r  eng501  SubjectId2 
maxt3r  phil507  SubjectId3 
spaced99 bkwv101  SubjectId1 
zontar33 eng501  SubjectId1 
zontar33 phil507  SubjectId2 

Wir haben jetzt die Daten, die wir benötigen, um das Endergebnis zu erstellen. Es wird durch Verschwenken orderedSubjects erhalten:

SELECT * 
FROM orderedSubjects 
PIVOT (
    MAX(SubjectId) 
    FOR col IN (SubjectId1, SubjectId2, SubjectId3) 
) AS p 

Die Anwendung der MAX ist nur erforderlich, weil die pivot Syntax die Verwendung einer Aggregationsfunktion erfordert. In dem vorliegenden Fall gibt es nur eine SubjectID in jeder Gruppe, so dass MAX ebenso einfach MIN sein könnte.

Beachten Sie auch, dass die SQL Server PIVOT Syntax erfordert, dass die Menge der generierten Pivot-Spalten in Anzahl festgelegt werden. In diesem Fall ist die Abfrage für drei Themen fest codiert. Wenn die Daten mehr Werte enthalten, als in die zugewiesene Anzahl von Spalten passen, wird der Überschuss verworfen.

Das Endergebnis ist wie folgt:

UserId  SubjectId1  SubjectId2  SubjectId3 
maxt3r  cpsc500   eng501   phil507 
spaced99 bkwv101   NULL   NULL 
zontar33 eng501   phil507   NULL 
2

Welche Datenbank verwenden Sie? Microsoft SQL Server (ab 2005) verfügt über PIVOT/UNPIVOT, um Zeilen in Spalten zu transponieren und umgekehrt. http://msdn.microsoft.com/en-us/library/ms177410.aspx

+0

Ich denke, PIVOT ist genau das, was ich brauche. Können Sie mir eine Beispielabfrage geben? –

+0

Nicht in der Nähe von echten Laptop mit SQL Server darauf. Pinal Dave hat hier darüber gebloggt http://blog.sqlauthority.com/2008/06/07/sql-server-pivot-und-unpivot-table-examples/ und auch die BOL-Verbindung, die ich oben gegeben habe, hat auch das Beispiel – Ash

+0

möchten Sie vielleicht in Erwägung ziehen, Ihre Antwort so zu bearbeiten, dass sie den Link aus Ihrem Kommentar enthält. –

Verwandte Themen