@Xedni: используйте <kbd> сохранить текст </ kbd>

отаю с некоторыми данными, которые в настоящее время хранятся с интервалом в 1 минуту, и выглядит так:

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

Это занимаетOpen значение с первой минуты 5,Close значение с последней минуты 5.High а такжеLow значения представляют самые высокиеhigh и самый низкийlow ставки по 5 минутному периоду.

Текущее решение

У меня есть решение, которое делает это (ниже), но он чувствует себя не элегантно, поскольку он опирается на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.

Ответы на вопрос(3)

Ваш ответ на вопрос