Abfrage, um Max / Min-Zeilendetails für mehrere Felder zu erhalten

Ich habe eine Tischstruktur ähnlich dem folgenden Beispiel:

DateTime V1 V2 V3 V4 10/10/10 12:10:00 71 24 33 40 10/10/10 12:00:00 75 22 44 12 10/10/10 12:30:00 44 21 44 33 10/10/10 12:20:00 80 11 88 12 

Mit DateTime-Feld ist das Unqiue und Key-Feld, ich möchte eine Abfrage, um min und max date time für jeden Wert, so dass es so etwas wie folgt zeigen:

 TYPE MIN MINDATETIME MAX MAXDATETIME V1 44 10/10/10 12:30:00 80 10/10/10 12:20:00 V2 11 10/10/10 12:20:00 24 10/10/10 12:10:00 V3 33 10/10/10 12:10:00 88 10/10/10 12:20:00 V4 12 10/10/10 12:20:00 40 10/10/10 12:10:00 

Wenn es mehrere Zeilen mit dem gleichen Min / Max-Wert gibt, dann sollte es die neueste bekommen.

Mit Inneren Verbinden Sie auf einem Feld, ich weiß, um die Details der Min / Max-Zeile für ein Feld zu bekommen, aber nur so kann ich denken, dass alles in einer Abfrage ist, um sie alle zu verbinden. Ich denke, es könnte eine bessere Lösung geben. Jede Hilfe wird geschätzt.

Ich verwende SQL server 2008.

Vielen Dank.

   
  • Unpivot in nützliche Zeilen ("normalisieren")
  • Ausarbeitung von MIN / MAX pro Typ, so dass MAX datetime, wenn Krawatten
  • Extrahieren Sie MIN / MAX-Werte

Hey presto …

 DECLARE @foo TABLE ( DateTimeKey datetime NOT NULL, V1 int NOT NULL, V2 int NOT NULL, V3 int NOT NULL, V4 int NOT NULL ); INSERT @foo (DateTimeKey, V1, V2, V3, V4) SELECT '10/10/10 12:10:00', 71, 24, 33, 40 UNION ALL SELECT '10/10/10 12:00:00', 75, 22, 44, 12 UNION ALL SELECT '10/10/10 12:30:00', 44, 21, 44, 33 UNION ALL SELECT '10/10/10 12:20:00', 80, 11, 88, 12; WITH cTE AS ( SELECT [Type], [Value], DateTimeKey, ROW_NUMBER() OVER (PARTITION BY [Type] ORDER BY [Value], DateTimeKey DESC) AS TypeRankMin, ROW_NUMBER() OVER (PARTITION BY [Type] ORDER BY [Value] DESC, DateTimeKey DESC) AS TypeRankMax FROM ( SELECT [Type], [Value], DateTimeKey FROM (SELECT DateTimeKey, V1, V2, V3, V4 FROM @foo) p UNPIVOT ([Value] FOR [Type] IN (V1, V2, V3, V4)) AS unp ) bar ) SELECT Mn.[Type], [MIN], MINDATETIME, [MAX], MAXDATETIME FROM ( SELECT [Type], [Value] AS [MIN], DateTimeKey AS MINDATETIME FROM cTE WHERE TypeRankMin = 1 ) Mn JOIN ( SELECT [Type], [Value] AS [MAX], DateTimeKey AS MAXDATETIME FROM cTE WHERE TypeRankMax = 1 ) Mx ON Mn.[Type] = Mx.[Type]; 

Sie können sowohl Max- als auch Min-Werte in einer einzigen Abfrage erhalten. Um max / min datetime zu bekommen, musst du die max / min-Abfrage wieder an die Tabelle (einmal pro jeden Wert)

etwas zur Wirkung von:

 select values.*, mint.timestamp, maxt.timestamp from (select MIN(value) as minv, MAX(value) as maxv from table group by value) values, table mint, table maxt where mint.value = values.minv maxt.value = values.maxv 

Nicht sicher, ob dies ist, was Sie nach, aber es scheint, diese grundlegende Fall zu lösen:

 create table t(a int,b int); insert into t(a,b) values(1,2),(2,3),(-1,-10); select max(t1.a),min(t1.a),max(t2.b),min(t2.b) from t as t1,t as t2; +-----------+-----------+-----------+-----------+ | max(t1.a) | min(t1.a) | max(t2.b) | min(t2.b) | +-----------+-----------+-----------+-----------+ | 2 | -1 | 3 | -10 | +-----------+-----------+-----------+-----------+ 

Ich würde mit der Normalisierung Ihrer data beginnen. Da V2 nicht von V1 abhängt, sollten sie nicht in der gleichen Reihe sein. Hier ist eine normalisierende Abfrage:

 SELECT DateTime, 'V1' as Type, V1 as Value FROM @data UNION ALL select DateTime, 'V2', V2 FROM @data UNION ALL select DateTime, 'V3', V3 FROM @data UNION ALL select DateTime, 'V4', V4 FROM @data 

Mit dem, was bleibt, ist die "Auswahl von datasätzen mit gruppenweise Maximum mit Krawatte" Problem. Ein path, das zu lösen ist:

 ;WITH normal AS ( SELECT DateTime, 'V1' as Type, V1 as Value FROM @data UNION ALL select DateTime, 'V2', V2 FROM @data UNION ALL select DateTime, 'V3', V3 FROM @data UNION ALL select DateTime, 'V4', V4 FROM @data ) SELECT * FROM (SELECT DISTINCT Type FROM normal) dd CROSS APPLY ( SELECT TOP 1 DateTime MINDATETIME, Value MIN FROM normal di WHERE di.Type = dd.Type ORDER BY Value, DateTime desc ) dimin CROSS APPLY ( SELECT TOP 1 DateTime MAXDATETIME, Value MAX FROM normal di WHERE di.Type = dd.Type ORDER BY Value desc, DateTime desc ) dimax 

Die dd Abfrage gibt die Typen zurück (V1, V2, …). Das erste cross apply sucht nach den Minimalwerten für diesen Typ und das zweite cross apply sucht nach den Maxima.

Ich lese die Frage und dachte: ich würde lieber das in PHP als SQL machen.

dann habe ich die Antworten gelesen und ich dachte: ich würde das lieber in PHP als SQL machen.