Pivot-Übersichten ( Kreuztabelle ) für Texte

Mehr
7 Jahre 2 Monate her - 7 Jahre 2 Monate her #814 von asu
Hallo,

die Möglichkeit sogenannte Kreuztabellen oder Pivot-Tabellen mit Hilfe der UserQueries zu gestalten, ist ja bekannt, für Filial-Umsätze auf HGR oder WGR Basis oder für Zeitachsen, dafür gibt es ja genügend Beispiele.

Beim Versuch sich eine Filialübersicht über ein Textfeld mit Hilfe unserer Procedure "UserPivot" wird man aber scheitern, da diese in der vorliegenden Form nicht für Textfelder ausgelegt ist.

Die Lösung: Sie können sich eine zweite UserPivot-Procedure anlegen ( siehe unten ), und diese dann verwenden, wenn Sie sich eine Kreuztabelle über Textfelder gestalten wollen.

Gruß
asu
create PROCEDURE [dbo].[UserPivotText]  
/*   
    Parameter  
    @Aggregate_Function (optional)  
         Aggregat-Funktion für die Pivot-Spalte, Default ist SUM  
    @Aggregate_Column  
         Name der Spalte, über die das Aggregat gebildet werden soll  
    @Aggregate_Column2 (optional)
         Name einer weiteren Spalte, über die das Aggregat gebildet werden soll  
    @TableOrView_Name  
         Name der Tabelle oder der View, über die die Pivot-Tabelle erzeugt werden soll  
         Dies kann auch ein gültiges SQL-Statement sein, wobei dies dann in Klammern stehen und einen Alias haben muss
         Beispiel '(SELECT  FROM UserLieferantenUmsatz WHERE (Filialnummer between 150 and 200) AND Periode=' + '''' + @Periode + ''') UserQ'  
    @Select_Column  
         Name der Spalte, für die Zeilen zurückgeliefert werden  
    @Select_Column2  
         Name einer zusätzlichen Spalte, für die Zeilen zurückgeliefert werden sollen
         Beispiel: @Select_Column = WGKürzel, @Select_Column2 = ArtikelNr
    @Info_Column1  
         Optional: Name einer zusätzlichen Spalte, für die Zeilen zurückgeliefert werden.
         Der Wert ist nicht in der Gruppierung enthalten und muss zur @Select_Column im Verhältnis 1:1 stehen
         Beispiel: @Select_Column = ArtikelNr, @Info_Column1 = Kurztext
    @Info_Column2  
         Optional: Name einer zusätzlichen Spalte, für die Zeilen zurückgeliefert werden.
         Siehe @Info_Column1
    @Pivot_Column  
         Name der Spalte, die in die Spalten transformiert werden soll  
    @Percentage
         0 (default) Es werden keine Prozentanteile mit ausgegeben
         1 Es wird jeweils der prozentuale Anteil am Gesamt als eigene Spalte mit erzeugt
    @Sum_Type
         0 Keine Zeilen mit Zwischensummen in das Ergebnis einfügen
         1 (default) Zwischensummen bei jedem Wechsel der @Select_Column ausgeben
         2 Zwischensummen für jede Kombination aus @Select_Column und @Select_Column2 ausgeben
    @DEBUG  
         0 (default) Keine Ausgabe von Debug-Meldungen
         1 Es werden Debug-Meldungen ausgegeben  
      
    Beispiel
         Es gibt eine UserQuery UserAktionsFilter mit den Daten der Tabelle AktionsStatistik und zusätzlich ein paar Feldern aus dem Artikel zur Info.
         Diese filtert die Filiale 0 aus (da die Summe in der Pivot-Tabelle separat ermittelt wird) und filtert und gruppiert 
         die gewünschten Werte schon einmal vor. Dies ist die Datengrundlage für die Pivot-Tabelle.
         Wichtig ist, dass es sich um eine View handelt!

		CREATE VIEW dbo.UserAktionsFilter
		AS
		SELECT     dbo.AktionsStatistik.*, dbo.Artikel.Kurztext AS Kurztext, dbo.Artikel.WGKürzel AS WGKürzel, dbo.Artikel.ArtikelGruppe AS ArtikelGruppe
		FROM         dbo.AktionsStatistik INNER JOIN
		                      dbo.Artikel ON dbo.AktionsStatistik.ArtikelNr = dbo.Artikel.ArtikelNr
		WHERE     (dbo.AktionsStatistik.Filialnummer > 0) AND (dbo.AktionsStatistik.Periode = 'S')
		

         Die UserQuery, die dann aufgerufen werden muss, sieht dann etwa so aus
		CREATE PROCEDURE UserQueryAktionAuswertung(@AktionsName Varchar(15)) AS
		DECLARE @V nvarchar(4000)
		SET @V = '(SELECT * FROM UserAktionsFilter WHERE Aktionsname=' + '''' + @AktionsName + ''') UserQ'
		EXEC UserPivot 'SUM', 'VerkaufMenge', 'VerkaufBetrag', @V, 'WGKürzel', 'ArtikelNr', 'Kurztext', 'Artikelgruppe', 'Filialnummer', 1, 1

         Wie man sieht, kann man hier beliebig viele Parameter einbauen und auch weitere Bedingungen an die View übergeben.
         Im obigen Beispiel wird der prozentuale Anteil der Filiale am Gesamtumsatz mit diesem Artikel ebenfalls mit ausgegeben.
         
   
*/

  @Aggregate_Function varchar(30) = 'SUM',  
  @Aggregate_Column   varchar(255),  
  @Aggregate_Column2   varchar(255) = '',  
  @TableOrView_Name   varchar(1024),  
  @Select_Column      varchar(255),  
  @Select_Column2     varchar(255) = '', 
  @Info_Column1       varchar(255) = '', 
  @Info_Column2       varchar(255) = '', 
  @Pivot_Column       varchar(255),
  @Percentage	bit = 0,   
  @Sum_Type     integer = 1,
  @DEBUG      bit = 0  
 AS  
 SET NOCOUNT ON  
 DECLARE @TransformPart   varchar(8000)  
 DECLARE @TransformTmp    varchar(8000)
 DECLARE @SQLColRetrieval nvarchar(4000)  
 DECLARE @SQLSelectIntro  varchar(8000)  
 DECLARE @SQLSelectFinal  varchar(8000)
 DECLARE @ColName         varchar(255)  
 DECLARE @ColName2        varchar(255)  
 DECLARE @ColValue	  varchar(255)
 DECLARE @Pos 		  integer
 DECLARE @StartPos 	  integer
 DECLARE @ColValueList    varchar(8000)

 IF @Aggregate_Function NOT IN ('SUM', 'COUNT', 'MAX', 'MIN', 'AVG', 'STDEV', 'VAR', 'VARP', 'STDEVP')    
  BEGIN RAISERROR ('Ungültige Aggregat-Funktion: %s', 10, 1, @Aggregate_Function) END  
 ELSE  
 BEGIN
  IF @Sum_Type = 0
          /* Kein Grouping() wenn keine Summen gewünscht sind */
	  SELECT @SQLSelectIntro = 'SELECT ' + QUOTENAME(@Select_Column) +  ', '  
	ELSE  
	  SELECT @SQLSelectIntro = 'SELECT CASE WHEN (GROUPING('  +   
	          QUOTENAME(@Select_Column)       +  
	     ') = 1) THEN ''Total'' ELSE '   +  
	     'CAST( + '                      +   
	                                 QUOTENAME(@Select_Column)       +  
	     ' AS varchar(255)) END As '    +   
	     QUOTENAME(@Select_Column)       +  
	     ', '  

  IF @Select_Column2 <> '' 
  BEGIN
     IF @Sum_Type = 0
          /* Kein Grouping() wenn keine Summen gewünscht sind */
	  SELECT @SQLSelectIntro = @SQLSelectIntro + ' ' + QUOTENAME(@Select_Column2) +  ', '  
	ELSE  
	  SELECT @SQLSelectIntro = @SQLSelectIntro +  
          ' CASE WHEN (GROUPING('  +   
          QUOTENAME(@Select_Column2)      +  
          ') = 1) THEN ''Total'' ELSE '   +  
          'CAST( + '                      +   
          QUOTENAME(@Select_Column2)      +  
          ' AS varchar(255)) END As '    +   
          QUOTENAME(@Select_Column2)      +  
          ', '
  END

  IF @Info_Column1 <> '' 
     IF @Sum_Type = 0
          /* Kein Grouping() wenn keine Summen gewünscht sind */
	  SELECT @SQLSelectIntro = @SQLSelectIntro + 
	     'MIN( '                        +   
             QUOTENAME(@Info_Column1)       +  
	     ') As '    +   
	     QUOTENAME(@Info_Column1)       +  
	     ', '  
	ELSE  
	  SELECT @SQLSelectIntro = @SQLSelectIntro +  
             ' CASE WHEN (GROUPING('  +   
             QUOTENAME(@Select_Column)      +  
             ') = 1 OR GROUPING('  +   
             QUOTENAME(@Select_Column2)      +  
             ') = 1) THEN '''' ELSE '  +  
	     'MIN( '                        +   
             QUOTENAME(@Info_Column1)       +  
	     ') END As '    +   
	     QUOTENAME(@Info_Column1)       +  
	     ', '  

  IF @Info_Column2 <> '' 
     IF @Sum_Type = 0
          /* Kein Grouping() wenn keine Summen gewünscht sind */
	  SELECT @SQLSelectIntro = @SQLSelectIntro + 
	     'MIN( '                        +   
             QUOTENAME(@Info_Column2)       +  
	     ') As '    +   
	     QUOTENAME(@Info_Column2)       +  
	     ', '  
	ELSE  
	  SELECT @SQLSelectIntro = @SQLSelectIntro +  
             ' CASE WHEN (GROUPING('  +   
             QUOTENAME(@Select_Column)      +  
             ') = 1 OR GROUPING('  +   
             QUOTENAME(@Select_Column2)      +  
             ') = 1) THEN '''' ELSE '  +  
	     'MIN( '                        +   
             QUOTENAME(@Info_Column2)       +  
	     ') END As '    +   
	     QUOTENAME(@Info_Column2)       +  
	     ', '  

  IF @DEBUG = 1 PRINT 'Intro :' + @SQLSelectIntro  

  /* Ermitteln der Werte, die in der Pivot-Spalte vorkommen.
     Die Liste der Werte wird als String in der Form [Wert1]@[Wert2]@ ... zurückgeliefert */

  SET @ColValueList = ''
  SET @SQLColRetrieval = 'SELECT @ColValueList = @ColValueList + QUOTENAME(CONVERT(VARCHAR(255),' +  
    QUOTENAME(CAST(@Pivot_Column AS VARCHAR(255))) +  '))+ ''@'' FROM ' +
    '(SELECT DISTINCT TOP 100 PERCENT' +   
    QUOTENAME(CAST(@Pivot_Column AS VARCHAR(255))) +   
    N' FROM ' + @TableOrView_Name + ' ORDER BY  ' +   
    QUOTENAME(CAST(@Pivot_Column AS VARCHAR(255))) + ') SQI'
   IF @DEBUG = 1 PRINT @SQLColRetrieval

  EXEC sp_executesql @SQLColRetrieval,   
                            N'@ColValueList varchar(8000) OUTPUT',   
                            @ColValueList OUTPUT  
   
  IF @DEBUG = 1 PRINT @ColValueList
  IF @ColValueList = '' 
	  BEGIN 
            RAISERROR ('Keine Pivot-Spalten gefunden', 10, 1) 
            RETURN
	  END  


  /* Jetzt den String mit den Werten der Pivot-Spalte auseinandernehmen und
     für jedes Element den passenden SQL-Befehl erzeugen */

  IF @Select_Column2 <> '' 
     SET @Select_Column2 = ', ' + @Select_Column2 

  IF @Aggregate_Column2 <> '' 
	BEGIN 
           SET @ColName = ' (' + @Aggregate_Column + ')'
           SET @ColName2 = @Aggregate_Column + ' '
        END
  ELSE
	BEGIN 
           SET @ColName = ''
           SET @ColName2 = ''
        END

  SET @TransformPart = ''
  SET @StartPos=1
  SELECT @Pos = charindex(']@',@ColValueList) + 1
  WHILE @Pos>1
  BEGIN
	SELECT @ColValue = substring(@ColValueList,@StartPos+1,@Pos-@StartPos-2)
        SET @TransformTmp =  @Aggregate_Function + '(CASE CAST(' +   
	    QUOTENAME(CAST(@Pivot_Column AS VARCHAR(255))) +   
	    ' AS VARCHAR(255)) WHEN ''' + @ColValue + ''' THEN ' + @Aggregate_Column +  
	    ' ELSE ''0'' END) AS [' + @ColValue + @ColName + ']'    
        SET @TransformPart = @TransformPart + @TransformTmp

        IF @Percentage = 1
           BEGIN 
		  SET @TransformTmp = ', CASE WHEN ' + @Aggregate_Function + '(' +   
		    QUOTENAME(CAST(@Aggregate_Column AS VARCHAR(255))) + ') = 0 THEN 0 ELSE ' +
		    @Aggregate_Function + '(CASE CAST(' +   
		    QUOTENAME(CAST(@Pivot_Column AS VARCHAR(255))) +   
		    ' AS VARCHAR(255)) WHEN ''' + @ColValue + ''' THEN ' + @Aggregate_Column + 
		    ' ELSE ''0'' END) /' + @Aggregate_Function + '(' +   
		    QUOTENAME(CAST(@Aggregate_Column AS VARCHAR(255))) + ') * 100 END AS [' + @ColValue + ' (' + @ColName2 + '%)]'
                  SET @TransformPart = @TransformPart + @TransformTmp
            END
	 /* SQL-Statement für die 2. Aggregatspalte zusammenbasteln (sofern vorhanden) */ 
	 IF @Aggregate_Column2 <> ''
 	    BEGIN
	        SET @TransformTmp = ', ' + @Aggregate_Function + '(CASE CAST(' +   
		    QUOTENAME(CAST(@Pivot_Column AS VARCHAR(255))) +   
		    ' AS VARCHAR(255)) WHEN ''' + @ColValue + ''' THEN ' + @Aggregate_Column2 +  
		    ' ELSE ''0'' END) AS [' + @ColValue + ' (' + @Aggregate_Column2 + ')]'    
	        SET @TransformPart = @TransformPart + @TransformTmp
	
	        IF @Percentage = 1
	           BEGIN 
			  SET @TransformTmp = ', CASE WHEN ' + @Aggregate_Function + '(' +   
			    QUOTENAME(CAST(@Aggregate_Column2 AS VARCHAR(255))) + ') = 0 THEN 0 ELSE ' +
			    @Aggregate_Function + '(CASE CAST(' +   
			    QUOTENAME(CAST(@Pivot_Column AS VARCHAR(255))) +   
			    ' AS VARCHAR(255)) WHEN ''' + @ColValue + ''' THEN ' + @Aggregate_Column2 + 
			    ' ELSE ''0'' END) /' + @Aggregate_Function + '(' +   
			    QUOTENAME(CAST(@Aggregate_Column2 AS VARCHAR(255))) + ') * 100 END AS [' + @ColValue + ' (' + @Aggregate_Column2 + ' %)]'
	                  SET @TransformPart = @TransformPart + @TransformTmp
	            END
            END

        SET @StartPos = @Pos + 1
	SELECT @Pos = charindex(']@',@ColValueList,@Pos+1) + 1
        IF @Pos > 1 SET @TransformPart = @TransformPart + ', '
  END

  IF @DEBUG = 1 PRINT 'Transform: ' + @TransformPart

  SET @SQLSelectFinal = ', ' + @Aggregate_Function + '(' +   
                        CAST(@Aggregate_Column As Varchar(255)) +  
                        ') As [Total'+ @ColName + ']'

  IF @Aggregate_Column2 <> ''
     SET @SQLSelectFinal = @SQLSelectFinal + ', ' + @Aggregate_Function + '(' +   
                            CAST(@Aggregate_Column2 As Varchar(255)) +  
                            ') As [Total ('+ @Aggregate_Column2 + ')]'

  SET @SQLSelectFinal = @SQLSelectFinal + ' FROM ' + @TableOrView_Name + ' GROUP BY ' +   
                        @Select_Column + @Select_Column2 
  /* Zwischensummen hinzufügen
  ROLLUP => Nur Zwischensummen für die erste Select-Spalte
  CUBE   => Zwischensummen für alle Kombinationen
  */
  IF @Sum_Type = 1 SET @SQLSelectFinal = @SQLSelectFinal + ' WITH ROLLUP'
  IF @Sum_Type = 2 SET @SQLSelectFinal = @SQLSelectFinal + ' WITH CUBE'

  IF @DEBUG = 1 PRINT 'FinalPart :' + @SQLSelectFinal  
  IF @DEBUG = 1 PRINT 'SQL :' + @SQLSelectIntro + @TransformPart + @SQLSelectFinal
  EXEC (@SQLSelectIntro + @TransformPart + @SQLSelectFinal)  
 END

"Wer Rechtschreibfehler findet, darf sie behalten."

Bitte Anmelden oder Registrieren um der Konversation beizutreten.