Ich bin mit einigen Daten arbeiten, die zur Zeit in Intervallen von 1 Minute gespeichert ist, die wie folgt aussehen:GROUP BY mit FIRST_VALUE und LAST_VALUE
CREATE TABLE #MinuteData
(
[Id] INT ,
[MinuteBar] DATETIME ,
[Open] NUMERIC(12, 6) ,
[High] NUMERIC(12, 6) ,
[Low] NUMERIC(12, 6) ,
[Close] NUMERIC(12, 6)
);
INSERT INTO #MinuteData
([Id], [MinuteBar], [Open], [High], [Low], [Close])
VALUES (1, '2015-01-01 17:00:00', 1.557870, 1.557880, 1.557870, 1.557880),
(2, '2015-01-01 17:01:00', 1.557900, 1.557900, 1.557880, 1.557880),
(3, '2015-01-01 17:02:00', 1.557960, 1.558070, 1.557960, 1.558040),
(4, '2015-01-01 17:03:00', 1.558080, 1.558100, 1.558040, 1.558050),
(5, '2015-01-01 17:04:00', 1.558050, 1.558100, 1.558020, 1.558030),
(6, '2015-01-01 17:05:00', 1.558580, 1.558710, 1.557870, 1.557950),
(7, '2015-01-01 17:06:00', 1.557910, 1.558120, 1.557910, 1.557990),
(8, '2015-01-01 17:07:00', 1.557940, 1.558250, 1.557940, 1.558170),
(9, '2015-01-01 17:08:00', 1.558140, 1.558200, 1.558080, 1.558120),
(10, '2015-01-01 17:09:00', 1.558110, 1.558140, 1.557970, 1.557970);
SELECT *
FROM #MinuteData;
DROP TABLE #MinuteData;
Die Werte Wechselkurse zu verfolgen, so dass für jedes Minuten-Intervall (bar), gibt es den Open
Preis als Minute gestartet und einen Close
Preis für das Minutenende. Die Werte High
und Low
repräsentieren die höchste und niedrigste Rate während jeder einzelnen Minute.
gewünschte Ausgabe
Ich suche diese Daten in 5-Minuten-Intervallen zu formatieren Sie die folgende Ausgabe zu erzeugen:
MinuteBar Open Close Low High
2015-01-01 17:00:00.000 1.557870 1.558030 1.557870 1.558100
2015-01-01 17:05:00.000 1.558580 1.557970 1.557870 1.558710
Dies nimmt den Open
Wert von der ersten Minute der 5 , Close
Wert von der letzten Minute der 5. Die High
und Low
Werte repräsentieren die höchsten high
und niedrigsten low
Raten über den 5-Minuten-Zeitraum.
Aktuelle Lösung
Ich habe eine Lösung, die dies tut (siehe unten), aber es fühlt sich unelegant wie es auf id
Werten beruht und sich selbst verbindet. Außerdem will ich es auf viel größere Datensätze laufen, so dass ich es in einer effizienteren Weise, wenn möglich zu tun war auf der Suche:
-- Create a column to allow grouping in 5 minute Intervals
SELECT Id, MinuteBar, [Open], High, Low, [Close],
DATEDIFF(MINUTE, '2015-01-01T00:00:00', MinuteBar)/5 AS Interval
INTO #5MinuteData
FROM #MinuteData
ORDER BY minutebar
-- Group by inteval and aggregate prior to self join
SELECT Interval ,
MIN(MinuteBar) AS MinuteBar ,
MIN(Id) AS OpenId ,
MAX(Id) AS CloseId ,
MIN(Low) AS Low ,
MAX(High) AS High
INTO #DataMinMax
FROM #5MinuteData
GROUP BY Interval;
-- Self join to get the Open and Close values
SELECT t1.Interval ,
t1.MinuteBar ,
tOpen.[Open] ,
tClose.[Close] ,
t1.Low ,
t1.High
FROM #DataMinMax t1
INNER JOIN #5MinuteData tOpen ON tOpen.Id = OpenId
INNER JOIN #5MinuteData tClose ON tClose.Id = CloseId;
DROP TABLE #DataMinMax
DROP TABLE #5MinuteData
Nacharbeits Versuch
Anstelle der obigen Abfragen, ich habe Ich benutze FIRST_VALUE und LAST_VALUE, da es scheint, was ich suche, aber ich kann nicht ganz mit der Gruppierung arbeiten, die ich mache. Es könnte eine bessere Lösung geben als das, was ich versuche, also bin ich offen für Vorschläge. Derzeit versuche ich, dies zu tun:
SELECT MIN(MinuteBar) MinuteBar5 ,
FIRST_VALUE([Open]) OVER (ORDER BY MinuteBar) AS Opening,
MAX(High) AS High ,
MIN(Low) AS Low ,
LAST_VALUE([Close]) OVER (ORDER BY MinuteBar) AS Closing ,
DATEDIFF(MINUTE, '2015-01-01 00:00:00', MinuteBar)/5 AS Interval
FROM #MinuteData
GROUP BY DATEDIFF(MINUTE, '2015-01-01 00:00:00', MinuteBar)/5
Das gibt mir die folgenden Fehler, die die FIRST_VALUE
verwendet ist und LAST_VALUE
wie die Abfrage ausgeführt wird, wenn ich diese Zeilen entfernen:
Spalte ‚# MinuteData.MinuteBar 'ist in der Auswahlliste ungültig, da sie weder in einer Aggregatfunktion noch in der GROUP BY-Klausel enthalten ist.
Die FIRST_VALUE angeben und last_value sind nicht wirklich Aggregatfunktionen wie Sie vielleicht denken. Sie sind eher wie row_number, wo sie über einen vollständigen Datensatz gefenstert sind. Problem ist, dass Sie versuchen, sie wie Aggregate zu benutzen, und deshalb schreit es Sie an. Ich muss jetzt sofort los, aber mein erster Gedanke war, das Datum auf eine Saite zu übertragen, die winzige Komponente zu teilen und sie in ihrer abgerundeten Form wieder zusammen zu kleben. – Xedni
danke für die Antwort, ich habe First_value nicht zuvor in Wut verwendet. Die Daten sind nicht wirklich mein Problem hier, ich habe eine Lösung für das, was zu funktionieren scheint, obwohl es bessere Wege geben könnte, das zu tun. Das Hauptproblem besteht darin, die Werte für Öffnen und Schließen für die Zeiträume von 5 Minuten zu erhalten. – Tanner
also Hoch und Niedrig ist einfach das höchste Hoch und das niedrigste niedrig, aber "offen" und "nah" sind das, was Sie Probleme haben, weil diese nur die ersten und letzten in dem Intervall sein sollten, unabhängig von ihrem Wert? Habe ich das richtig? – Xedni