Pracuję z niektórych danych, które są obecnie przechowywane w odstępach 1-minutowych, który wygląda tak:Korzystanie z GROUP BY FIRST_VALUE i 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;
Wartości śledzić kursów walutowych, więc za każdym przedziale minut (bar), cena zaczyna się od minuty Open
a cena za minutę. Wartości High
i Low
reprezentują najwyższą i najniższą stawkę podczas każdej minuty.
Pożądany Wyjście
szukam formatowanie tych danych do 5-minutowych odstępach, aby następujący wynik:
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
ta przyjmuje wartość Open
od pierwszej minuty z 5 , wartość Close
od ostatniej minuty 5. Wartości High
i Low
reprezentują najwyższe wartości high
i najniższe wartości low
w okresie 5 minut.
obecne rozwiązanie
Mam rozwiązanie, które wykonuje to (poniżej), ale czuje się nieeleganckie, gdyż opiera się na wartościach i samo id
łączy. Również mam zamiar uruchomić go na znacznie większych zbiorów danych więc szukałem to zrobić w sposób bardziej efektywny, jeśli to możliwe:
-- 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
Rework próba
Zamiast z powyższych pytań, mam patrzyłem na używanie FIRST_VALUE i LAST_VALUE, ponieważ wydaje mi się, że to jest to, o co prosiłem, ale nie mogę tego zrobić, pracując z grupą, którą robię. Może być lepsze rozwiązanie niż to, co próbuję zrobić, więc jestem otwarty na sugestie. Obecnie staram się to zrobić:
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
To daje mi poniższy błąd, który jest związany z FIRST_VALUE
i LAST_VALUE
jak biegnie zapytanie czy mogę usunąć te linie:
kolumnie „# MinuteData.MinuteBar "jest niepoprawny na liście select, ponieważ nie jest zawarty ani w funkcji agregującej, ani w klauzuli GROUP BY.
FIRST_VALUE i last_value rzeczywistości nie są zagregowane funkcje jak mogłoby się wydawać. Są bardziej podobne do row_number, gdzie są wyświetlane w pełnym zestawie danych. Problem polega na tym, że próbujesz używać ich jak agregatów, i dlatego to na ciebie krzyczy. Muszę teraz wyruszyć, ale moją pierwszą myślą było rzucić datę na napis, podciąć minutę i połączyć taśmę w zaokrągloną formę. – Xedni
dzięki za odpowiedź, nie użyłem first_value w gniewie przed. daty nie są moim problemem, mam rozwiązanie tego, które wydaje się działać, chociaż mogą istnieć lepsze sposoby na to. głównym problemem jest uzyskiwanie wartości otwartych i zamkniętych dla okresów 5-minutowych. – Tanner
tak wysokie i niskie to po prostu najwyższy najwyższy i najniższy poziom najniższy, ale "otwarte" i "bliskie" są tym, z czym masz problemy, ponieważ te powinny być po prostu pierwsze i ostatnie w przedziale, niezależnie od ich wartości? Czy mam to prawo? – Xedni