Oracle-MIN als analytische Funktion - merkwürdiges Verhalten mit ORDER BY?
Diesem speziellen Fall wurde destilliert von einem Beispiel, wo der Programmierer davon ausgegangen, dass für zwei Sendungen in einen tank car, line #1 würde zuerst geladen werden. Ich korrigiert dies, dass für die Belastung in beliebiger Reihenfolge durchgeführt werden - allerdings habe ich entdeckt, dass MIN() OVER (PARTITION BY)
ermöglicht eine ORDER BY
in Oracle (dies ist nicht erlaubt im SQL-Server), und zusätzlich, es ändert das Verhalten der Funktion, wodurch die ORDER BY
offenbar werden Hinzugefügt, um die PARTITION BY
.
WITH data AS (
SELECT 1 AS SHIPMENT_ID, 1 AS LINE_NUMBER, 2 AS TARE, 3 AS GROSS FROM DUAL
UNION ALL
SELECT 1 AS SHIPMENT_ID, 2 AS LINE_NUMBER, 1 AS TARE, 2 AS GROSS FROM DUAL
)
SELECT MIN(tare) OVER (PARTITION BY shipment_id) first_tare
,MAX(gross) OVER (PARTITION BY shipment_id) last_gross
,FIRST_VALUE(tare) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER) first_tare_incorrect
,FIRST_VALUE(gross) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER DESC) last_gross_incorrect
,MIN(tare) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER) first_tare_incorrect_still
,MAX(gross) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER DESC) last_gross_incorrect_still
,MIN(tare) OVER (PARTITION BY shipment_id, LINE_NUMBER) first_tare_incorrect_still2
,MAX(gross) OVER (PARTITION BY shipment_id, LINE_NUMBER) last_gross_incorrect_still2
FROM data
Einer SQL-Server-Beispiel (mit nicht zutreffenden code auskommentiert):
WITH data AS (
SELECT 1 AS SHIPMENT_ID, 1 AS LINE_NUMBER, 2 AS TARE, 3 AS GROSS -- FROM DUAL
UNION ALL
SELECT 1 AS SHIPMENT_ID, 2 AS LINE_NUMBER, 1 AS TARE, 2 AS GROSS -- FROM DUAL
)
SELECT MIN(tare) OVER (PARTITION BY shipment_id) first_tare
,MAX(gross) OVER (PARTITION BY shipment_id) last_gross
-- ,FIRST_VALUE(tare) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER) first_tare_incorrect
-- ,FIRST_VALUE(gross) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER DESC) last_gross_incorrect
-- ,MIN(tare) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER) first_tare_incorrect_still
-- ,MAX(gross) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER DESC) last_gross_incorrect_still
,MIN(tare) OVER (PARTITION BY shipment_id, LINE_NUMBER) first_tare_incorrect_still2
,MAX(gross) OVER (PARTITION BY shipment_id, LINE_NUMBER) last_gross_incorrect_still2
FROM data
Frage also: Was ist Oracle tut und warum und ist es richtig?
- ich denke, der Denali hat das jetzt
- Smith ja, das Verhalten, die sollten identisch sein, und die
ORDER BY
sollte Auswirkungen auf das Verhalten. Ich verstehe nicht, warum Oracle nicht gegen dieORDER BY
wie SQL Server ist, und dann, WARUM es wirkt sich auf das Verhalten. - Werfen Sie einen Blick auf diesen link geniiius.com/blog/t-sql-enhancements-over-clause Es erklärt das Verhalten, die Sie Fragen, die auf SQL Server Denali, und warum es Sinn macht
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie hinzufügen, ein
ORDER BY
zu denMIN
analytische Funktion, schalten Sie es in einen "min-soweit" - Funktion eher als eine Allgemeine minimum. Für die Letzte Zeile für das, was Sie sind-Partitionierung durch, die Ergebnisse werden die gleichen sein. Aber die vorherigen Zeilen haben vielleicht ein anderes "min-soweit" als die Gesamt-minimum.Mithilfe der
EMP
Tabelle als Beispiel können Sie sehen, dass das Mindestgehalt bisher für die Abteilung schließlich konvergiert auf die insgesamt mindestens für die Abteilung. Und Sie können sehen, dass die "min-soweit" - Wert für jede Abteilung nimmt als niedrigere Werte angetroffen werden.Natürlich würde es mehr Sinn machen, verwenden Sie diese form der Analyse-Funktion, wenn du versuchst, etwas zu machen, berechnen Sie eine persönliche Bestzeit, die Sie verwenden können, wie ein Vergleich in zukünftigen Perioden. Wenn Sie tracking eine individuelle Verringerung golf erzielt, Meile Zeiten oder Gewicht, Anzeige persönliche Bestleistungen kann eine form der motivation.
FIRST_TARE
gibt Sie den minimalen Wert vonTARE
für jedenSHIPMENT_ID
was Sie wollen.FIRST_TARE_INCORRECT_STILL
gibt Sie den minimalen Wert vonTARE
für jedenSHIPMENT_ID
wurde bisher begegnet. Die "min-soweit" der Linie 1 ist 2, weil das der einzige Wert, den es gesehen hat. Die "min-soweit" der Linie 2 ist 1. UndFIRST_TARE_INCORRECT_STILL2
gibt Sie die minimaleTARE
für jedenSHIPMENT_ID, LINE_NUMBER
. Da ist vermutlich einzigartig, das wird nur wieder dasTARE
der Zeile.MAX
Gegenzug die größteGROSS
bisher für dieSHIPMENT_ID
beginnend mit dem größtenLINE_NUMBER
und arbeitet rückwärts. Das ist schwer, um Ihren Kopf herum, aber Oracle scheint zu tun, was Sie Fragen es.