MSSQL Zweistufige Sortierung vertikal + horrizontal



  • Hi,

    meine Tabelle hat drei Spalten, 'Grp', 'Cnt' und 'Val'. Der Inhalt sieht folgendermaßen aus:

    'Grp' | 'Cnt' | 'Val'
    ------+-------+-------
      1   |   1   |  11
      1   |   2   |  12
      1   |   3   |  13
      2   |   1   |  21
      2   |   2   |  22
      2   |   3   |  23
      3   |   1   |  31
      3   |   2   |  32
      3   |   3   |  33
    

    Die Einträge lassen sich also logisch über 'Grp' gruppieren, innerhalb jeder "Gruppe" wird 'Cnt' hochgezählt und mit Werten belegt.

    Ich möchte aus dieser Tabelle heraus gerne eine Abfrage erstellen, die mir die 'Val'-Werte der Gruppen zu den 'Cnt'-Werten darstellt. Das ganze soll so aussehen, dass in der ersten Spalte die 'Cnt'-Werte stehen und dahinter die 'Val'-Werte für jede Gruppe in jeweils einer eigenen Spalte. Etwa so:

    'Cnt' | 'Grp1' | 'Grp2' | 'Grp3'
    ------+--------+--------+--------
      1   |   11   |   21   |   31
      2   |   12   |   22   |   32
      3   |   13   |   23   |   33
    

    Ich würde jetzt hergehen und das ganze über JOINs lösen. Dafür müsste ich aber für jeden 'Grp'-Wert einen extra JOIN erstellen. Das können durchaus einige werden und die Anzahl ist auch noch variabel.
    Gibt es nicht eine einfachere Möglichkeit für so eine Abfrage?



  • Unter MS Access kenne ich die Möglichkeit, Kreuztabellen zu definieren. Aber ich hab' keine Ahnung, von wie vielen Datenbanken das unterstützt wird.



  • Kreuztabelle war genau das richtige Stichwort 😉

    So wirds gemacht:

    SELECT 
      Cnt,
      '1' AS Grp1,
      '2' AS Grp2,
      '3' AS Grp3
    
    FROM
      MyTbl
    
    PIVOT (
      MAX(Val) FOR Grp IN ('1','2','3')
    ) AS PvtTbl;
    

    Zwei Sachen stören mich allerdings noch. Die eine ist, dass ich für Val unbedingt eine Aggregatfunktion verwenden muss. Aber das ist auch nur Kosmetik, hab sowieso nur ein Ergebnis, da kann ich mit MAX leben. Die zweite ist, dass ich bisher keine Syntax gefunden hab, wie ich in die IN-Klausel ein SELECT bekomme.
    Sowas hätte mir vorgeschwebt:

    ...
      MAX(Val) FOR Grp IN (SELECT Grp FROM MyTbl GROUP BY Grp)
    ...
    

    Sonst müsste ich ja doch wieder jede Spalte extra angeben...



  • heimchen schrieb:

    Die eine ist, dass ich für Val unbedingt eine Aggregatfunktion verwenden muss. Aber das ist auch nur Kosmetik, hab sowieso nur ein Ergebnis, da kann ich mit MAX leben.

    Was sollte denn sonst passieren, wenn eine Kombination aus Grp und Cnt mehrfach vorkommt.

    Die zweite ist, dass ich bisher keine Syntax gefunden hab, wie ich in die IN-Klausel ein SELECT bekomme.
    Sowas hätte mir vorgeschwebt:

    ...
      MAX(Val) FOR Grp IN (SELECT Grp FROM MyTbl GROUP BY Grp)
    ...
    

    Sonst müsste ich ja doch wieder jede Spalte extra angeben...

    Hast du schonmal die WHERE-Klausel ausprobiert?

    SELECT 
      Cnt,
      '1' AS Grp1,
      '2' AS Grp2,
      '3' AS Grp3
    
    FROM
      MyTbl
    WHERE
      Grp IN (SELECT ...)
    PIVOT (
      MAX(Val) FOR Grp
    ) AS PvtTbl;
    


  • Die WHERE Klausel könnt ich mir auch Sparen, will ja alle haben. Aber genau das ist das Problem, PIVOT besteht bei mir auf die IN Klausel und in dieser darf ich kein SELECT verwenden.



  • Dann wirst du dir vermutlich erst alle Gruppen holen müssen (SELECT DISTINCT Grp FROM ...), aus denen dann einen passenden IN String basteln, und mit diesem die Abfrage erstellen.



  • Ja, was anderes hab ich dazu bisher auch nicht gefunden...


Log in to reply