PIVOT-Daten aus der MSSQL-Abfrage und Abrufen in die PHP-Ansicht

Dec 04 2020

Ich habe eine MSSQL 2005-Datenbank mit folgenden Abfrageinhalten:

Nopas Code Name Bestellung
00115301 D031 ADAM 1
00130015 D031 ADAM 2
00149998 D026 JAMES 1
00149970 D028 FIKI 1
00142641 D028 FIKI 2
00127700 D028 FIKI 3

Aus Berichtsgründen muss ich eine Tabelle ausgeben wie:

ADAM JAMES FIKI ... (dynamischer inhaltsbasierter neuer Datensatz)
00115301 00149998 00149970 ...
00130015 - - 00142641 ...
- - - - 00127700 ...

Kann mir jemand helfen??

Antworten

Jason Dec 04 2020 at 16:46

Sie können einen Pivot mit CASEAnweisungen ausführen . Dies ist im Grunde die manuelle Art des Schwenkens. Wenn Sie vor 2005 eine Version von SQL Server verwenden würden, müssten Sie diesen Weg gehen. SQL Server 2005 hat die PIVOT-Funktion hinzugefügt .

Da es dynamisch sein muss, müssen Sie dynamisches SQL verwenden . Es ist viel Beinarbeit, aber definitiv machbar.

Ich werde Ihren Tabelleninhalt in einer globalen temporären Tabelle erstellen (muss global sein, um in dynamischem SQL zu funktionieren).

-- CREATE GLOBAL TEMPORARY TABLE
CREATE TABLE ##tablename (
  [nopas] VARCHAR(8),
  [code] VARCHAR(4),
  [name] VARCHAR(64),
  [order] SMALLINT
);

INSERT INTO ##tablename
  ([nopas], [code], [name], [order])
VALUES
 ('00115301','D031','ADAM',  1)
,('00130015','D031','ADAM',  2)
,('00149998','D026','JAMES', 1)
,('00149970','D028','FIKI',  1)
,('00142641','D028','FIKI',  2)
,('00127700','D028','FIKI',  3);

Als nächstes gehe ich SELECTnur die eindeutigen Namen in eine andere temporäre Tabelle und ordne sie einem zu, IDENTITYmit dem ich in einer for-Schleife durchlaufen kann.

SELECT IDENTITY(INT, 1,1) as [id], [name] 
INTO #temp
FROM ##tablename
GROUP BY [name];

Jetzt kommt der schwierige Teil. Das PRINT @dynSQLgeneriert, was ich dynamisch erreichen möchte (siehe unten). Wir müssen SELECTdas [order], [name]und [nopas]für das Endergebnis. Wir drehen uns [name]im zweiten Teil der Erklärung um und aggregieren nach MAX([nopas]); Da wir jedoch eine [order]Gruppierung in Ihrem ursprünglichen Tabelleninhalt enthalten, wird nur die MAX([nopas])basierend auf dem MAXWert einer einzelnen Zeile abgerufen . Das Ergebnis ist also, dass die Aggregation entfernt wird. Wenn Sie keine haben , haben [order]Spalte in der ursprünglichen Inhalt, müssten wir das verwenden ROW_NUMBER () -Funktion * PARTITIONED BYdas , [name]dass zu erzeugen [order].

BEARBEITEN: Ich habe festgestellt, dass die ROW_NUMBER()Funktion nur in SQL Server 2012 und höher verfügbar ist.

-- PRINT @dynSQL result
SELECT * FROM
(SELECT [order], [name], [nopas]
  FROM ##tablename) AS sourceTable
PIVOT(
MAX([nopas])
FOR [name] IN ([ADAM],[FIKI],[JAMES])
) AS pivotTable;
-- The leg work to create the dynamic SQL.
DECLARE @count INT = 1;
DECLARE @max INT = (SELECT MAX(id) FROM #temp);
DECLARE @dynSQL VARCHAR(2048) = 'SELECT * FROM
(SELECT [order], [name], [nopas]
  FROM ##tablename) AS sourceTable
PIVOT(
MAX([nopas])
FOR [name] IN (';

SET @count = 1;
WHILE(@count <= @max)
BEGIN
  SET @dynSQL += '[' + (SELECT [name] FROM #temp WHERE id = @count) + '],';
  SET @count += 1;
END

SET @dynSQL = LEFT(@dynSQL, DATALENGTH(@dynSQL) -1) + ')
) AS pivotTable;';

PRINT @dynSQL;
EXEC (@dynSQL);

DROP TABLE ##tablename;
DROP TABLE #temp;

Oh, wenn Sie die [order]Spalte aus dem Ergebnis entfernen möchten . Sie können SELECT * INTO ##newGlobalTablein der dynamischen SQL und dann ALTERdie neue Tabelle und DROPdie Spalte verwenden.