我與當前存儲以1分鐘爲間隔的一些數據,看起來像這樣的工作:使用GROUP BY與FIRST_VALUE和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;
值跟蹤貨幣匯率,所以爲每分鐘間隔(條),分鐘開始時的價格爲Open
,分鐘結束時的價格爲Close
。 High
和Low
值表示每個單獨分鐘期間的最高和最低速率。
所需的輸出
我正在尋找在以5分鐘的間隔,以重新格式化該數據以產生以下輸出:
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
這從5的第一分鐘取Open
值,來自5的最後一分鐘的Close
值。該High
和Low
值表示在5分鐘期間內的最高high
和最低low
率。
目前的解決方案
我做這個(下圖)的解決方案,但因爲它依賴於id
價值觀和自我加入感覺不雅。另外,我打算在更大的數據集上運行它,所以我一直在尋找這樣做更有效的方式,如果可能的:
-- 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
返修嘗試
代替上述的查詢,我已經一直在尋找使用FIRST_VALUE和LAST_VALUE,因爲它似乎是我所追求的,但我無法完全理解我正在使用的分組。可能有比我想要做的更好的解決方案,所以我願意接受建議。目前我正在努力做到這一點:
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
這給了我下面的錯誤,這是關係到FIRST_VALUE
和LAST_VALUE
作爲查詢運行,如果我刪除這些行:
列「# MinuteData.MinuteBar'在選擇列表中無效,因爲它不包含在聚合函數或GROUP BY子句中。
的FIRST_VALUE和LAST_VALUE實際上不是聚合函數像你想象的。它們更像row_number,它們被放在一個完整的數據集上。問題是你想要像聚合物一樣使用它們,這就是爲什麼它會對你大喊大叫。我現在必須出頭,但我的第一個想法是將日期轉換爲一個字符串,將分鐘組件串出並將它們以圓形形式粘貼在一起。 – Xedni
感謝您的回覆,我之前沒有在憤怒中使用過first_value。日期在這裏並不是我的問題,我有一個解決方案,似乎正在工作,雖然可能有更好的方法來做到這一點。主要問題是獲得5分鐘期間的開盤價和收盤價。 – Tanner
所以高和低分別是最高和最低,但是'open'和'close'是你遇到的問題,因爲那些應該是間隔中的第一個和最後一個,而不管它們的值如何?我有這個權利嗎? – Xedni