2016-08-16 4 views
1

Ich habe eine umfangreiche Ansicht erstellt, die bestimmte Vorkommen basierend auf verschiedenen statistischen Modellen simuliert. Diese Modelle sind in jeder Spaltenüberschrift durch eine Zahl definiert und der Maximalwert einer Zeile ist das beste Modell.Abrufen des Spaltennamens, der den Maximalwert einer Zeile enthält

Die erzeugte Tabelle sieht (teilweise) folgendermaßen aus:

+--------+----+------+------+------+------+------+------+ 
| Number | LI | PHSE | 0505 | 0506 | 0507 | 0508 | 0509 | [...] etc. 
+--------+----+------+------+------+------+------+------+ 
| 100254 | 2 | M1 | 44 | 46 | 45 | 44 | 44 | 
| 100254 | 2 | M2 | 36 | 36 | 35 | 37 | 37 | 
| 100254 | 2 | M3 | 5 | 5 | 5 | 5 | 5 | 
| 100254 | 2 | R1 | 34 | 36 | 37 | 37 | 37 | 
| 100254 | 2 | R2 | 41 | 41 | 40 | 41 | 41 | 
| 100329 | 1 | M1 | 37 | 38 | 38 | 38 | 39 | 
| 100329 | 1 | M2 | 31 | 29 | 28 | 29 | 29 | 
| 100329 | 1 | M3 | 6 | 6 | 6 | 6 | 6 | 
| 100329 | 1 | R1 | 29 | 29 | 29 | 30 | 30 | 
| 100329 | 1 | R2 | 25 | 26 | 26 | 27 | 26 | 
+--------+----+------+------+------+------+------+------+ 
    [...] etc. 

Jetzt möchte ich den höchsten Wert in jeder Zeile zu finden und die entsprechenden Spaltennamen als solche angezeigt werden;

| Number | LI | PHSE | MAXCOL | 
+--------+----+------+--------+ 
| 100254 | 2 | M1 | 0506 | 
| 100254 | 2 | M2 | 0508 | 
| 100254 | 2 | M3 | 0505 | 
| 100254 | 2 | R1 | 0507 | 
| 100254 | 2 | R2 | 0505 | 
+--------+----+------+--------+ 
    [...] etc. 

Dieser von 100.254 abgeleitet ist - 2 - M1 größte Wert 46 auftretenden in Spalte 0506 usw.

Ich habe um mit PIVOT Funktionen liebäugelt aber ohne Erfolg. Ich habe auch nach einem Index/Match-Äquivalent wie in Excel gesucht, aber da ich nicht auf Spaltenüberschriften als Werte verweisen kann, wird dies offensichtlich nicht funktionieren (und auch keine solche Funktion gefunden haben).

Jede Hilfe würde sehr geschätzt werden.


UPDATE pro Damien Kommentar:

Ein Auszug aus dem Code, der dazu geführt hat:

SELECT DISTINCT sub2.Number, sub2.LI, sub2.PHSE 
, sum(sub2.[0505]) over (partition by sub2.Number, sub2.LI, sub2.PHSE) as '0505' 
, sum(sub2.[0506]) over (partition by sub2.Number, sub2.LI, sub2.PHSE) as '0506' 
[...] etc. /*64 rows*/ 

FROM 
    (SELECT DISTINCT sub.* 
    , CASE WHEN sub.MF > sub.[5PAV] - sub.[5PSTDEV] THEN 1 ELSE 0 END AS '0505' 
    , CASE WHEN sub.MF > sub.[5PAV] - sub.[6PSTDEV] THEN 1 ELSE 0 END AS '0506' 
    [...] etc. /*64 rows*/ 

    FROM 
     (SELECT DISTINCT ra.* 
     , sum(ra.qtyr) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 5 preceding AND 1 preceding)/
     sum(ra.qtyu) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 5 preceding AND 1 preceding) AS '5PAV' 
     , sum(ra.qtyr) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 6 preceding AND 1 preceding)/
     sum(ra.qtyu) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 6 preceding AND 1 preceding) AS '6PAV' 
     [...] etc. /*8 rows*/ 

     , stdev(ra.MF) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 4 preceding AND CURRENT row) AS '5PSTDEV' 
     , stdev(ra.MF) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 5 preceding AND CURRENT row) AS '6PSTDEV' 
     [...] etc. /*8 rows*/ 

     FROM ra 
     ) AS sub 
    ) AS sub2 

Kein Zweifel, dass dies eine der ineffektiven Nutzung von SQL sein kann, aber die Zeit - Druck und Unerfahrenheit haben mich dazu gebracht, es so zu schreiben.

Alle Vorschläge, diesen Code zu ändern und das gewünschte Tabellenergebnis effizienter zu erreichen, würden ebenfalls sehr geschätzt werden.


EDIT pro Antons Antwort;

Der obige Code, der als pvt zusammengefasst ist, fährt wie folgt fort;

SELECT Number, LI, PHSE, combo, hitrate 

FROM (...) AS pvt 
UNPIVOT 
(Hitrate FOR Combo IN (
         [0505], 
         [0506], 
         [...] etc.)) AS upvt 

Große Lösung für ein unelegantes Problem.

+0

Sie gemacht haben den Fehler, eine Datenbanktabelle zu behandeln, als ob es sich um eine Tabelle ist. Dies ist nicht der Fall, und Sie haben a) wiederholt Spalten mit dem gleichen "Typ" von Daten und b) Daten nicht als Daten gespeichert, sondern in den Metadaten (hier, Spaltennamen) gespeichert. Wenn Sie die Daten an erster Stelle korrekt modelliert hätten (mit zwei Spalten für das Modell und den Wert und so viel mehr Zeilen, aber weniger Spalten), wäre die Abfrage einfach zu schreiben. –

+0

@Damien_The_Unbeliever das macht Sinn. Die Daten werden durch Unterabfragen in diesem Format generiert, so dass die Quelle nicht das Problem ist. Es ist die Methode, die ich auf diesen Punkt angewendet habe, die unwirksam scheint; Obwohl das 'Unpivot' die Daten in der von Ihnen vorgeschlagenen Weise neu arrangiert, scheint es ein sehr ineffektiver Umweg zu sein. Ich werde die obige Frage bearbeiten, um das zu vertiefen und zu sehen, wie der Code viel effizienter gestaltet werden kann. Ich bin so weit gegangen, Koalesce-Funktionen in Excel zu verwenden, um die Abfrage unter Berücksichtigung aller beteiligten Variablen zu schreiben. Es ist dumm ich weiß, aber Zeitdruck und begrenzte Erfahrung führte mich zu dieser Methode – Sambo

Antwort

1

Sie müssen UNPIVOT verwenden, nicht PIVOT

https://msdn.microsoft.com/en-us/library/ms177410.aspx

Wenn die Anzahl der Spalten variabel ist, haben Sie die dynamische SQL verwenden, um die Liste der Spalten zu konstruieren

+0

Großartig! Wahrscheinlich nicht die raffinierteste Art, zu dem Schluss zu kommen, aber es hat sicherlich funktioniert! – Sambo

0

ich CROSS APPLY verwenden würde als follows:

WITH Src AS 
(
    SELECT * FROM (VALUES 
    (100254, 2, 'M1', 44, 46, 45, 44, 44), 
    (100254, 2, 'M2', 36, 36, 35, 37, 37), 
    (100254, 2, 'M3', 5, 5, 5, 5, 5), 
    (100254, 2, 'R1', 34, 36, 37, 37, 37), 
    (100254, 2, 'R2', 41, 41, 40, 41, 41), 
    (100329, 1, 'M1', 37, 38, 38, 38, 39), 
    (100329, 1, 'M2', 31, 29, 28, 29, 29), 
    (100329, 1, 'M3', 6, 6, 6, 6, 6), 
    (100329, 1, 'R1', 29, 29, 29, 30, 30), 
    (100329, 1, 'R2', 25, 26, 26, 27, 26)) T(Number, LI, PHSE, [0505], [0506], [0507], [0508], [0509]) 
) 
SELECT Number, LI, PHSE, MaxCol 
FROM Src 
CROSS APPLY (SELECT TOP 1 * FROM (VALUES 
    ('0505', [0505]), 
    ('0506', [0506]), 
    ('0507', [0507]), 
    ('0508', [0508]), 
    ('0509', [0509]) 
    ) T(MaxCol, Val) ORDER BY Val DESC) Q 

Beachten Sie, dass gleiche Spalten zufällig ausgewählt werden können, sofern nicht ein zusätzlicher Wert angegeben wird. d.h. MaxCol.

aktualisieren Sie müssen dynamische Abfrage, wie man folgendermaßen vor:

DECLARE @sql nvarchar(MAX) = 
    'SELECT Number, LI, PHSE, MaxCol 
FROM Src 
CROSS APPLY (SELECT TOP 1 * FROM (VALUES' +STUFF(
    (SELECT ',(', QUOTENAME(name, '''')+','+QUOTENAME(name)+')' 
    FROM sys.columns 
    WHERE object_id=OBJECT_ID('Src') AND name NOT IN ('Number', 'LI', 'PHSE') 
    FOR XML PATH('')), 1, 1, '')+') T(MaxCol, Val) ORDER BY Val DESC) Q'; 
EXEC(@sql); 

Src ist Ihre Tabellennamen, sie entsprechend ersetzen.

+0

Danke, aber die Tabelle geht 64 Spalten über und 52K Datensätze nach unten. Keine Option ... – Sambo

+0

In diesem Fall benötigen Sie dynamische Abfrage, siehe aktualisierte Antwort. –

0

Wenn Sie alle MAXCOL (gleiche Spalten) sehen möchten versuchen Sie dies:

CREATE TABLE table1 (
Number NUMERIC(10), 
LI numeric(10), 
PHSE NVARCHAR(10), 
[0505] numeric(10), 
[0506] numeric(10), 
[0507] numeric(10), 
[0508] numeric(10), 
[0509] numeric(10)) 

INSERT INTO table1 VALUES(100254,2,'M1',44 ,46 ,45 ,44,44) 
INSERT INTO table1 VALUES(100254,2,'M2',36,36,35,37,37) 
INSERT INTO table1 VALUES(100254,2,'M3',5,5,5,5,5) 
INSERT INTO table1 VALUES(100254,2,'R1',34,36,37,37,37) 
INSERT INTO table1 VALUES(100254,2, 'R2',41,41,40,41,41) 
INSERT INTO table1 VALUES(100329,1, 'M1',37,38,38,38,39) 
INSERT INTO table1 VALUES(100329,1, 'M2',31,29,28,29,29) 
INSERT INTO table1 VALUES(100329,1, 'M3',6,6,6,6,6) 
INSERT INTO table1 VALUES(100329,1, 'R1',29,29,29,30,30) 
INSERT INTO table1 VALUES(100329,1, 'R2',25,26,26,27,26) 

SELECT * 
INTO #UNPIVOT 
FROM table1 
UNPIVOT (num 
FOR MAXCOL IN ([0505],[0506],[0507],[0508],[0509])) AS k 

SELECT A.Number,A.LI,A.PHSE,A.num,B.MAXCOL FROM 
(SELECT number,LI,PHSE,MAX(num) AS num FROM #UNPIVOT GROUP BY number,LI,PHSE) A 
LEFT JOIN 
(SELECT * FROM #UNPIVOT) B ON A.num=B.num AND A.Number=B.Number AND A.LI=B.LI AND A.PHSE=B.PHSE 
+0

Danke, aber die Tabelle geht 64 Spalten über und 52K zeichnet auf. Keine Option... – Sambo

Verwandte Themen