SQL Server: первая и последняя строка, составляющая агрегацию - PullRequest
1 голос
/ 22 ноября 2011

У меня есть таблица, в которой хранятся данные о движении цены за минуту.Каждая запись содержит последнюю минуту открытия, максимума, минимума, закрытия и объема

CREATE TABLE TimeBar (
  Instrument varchar(20),
  BarTimeStamp datetimeoffset(7),
  Open decimal(18, 5),
  High decimal(18, 5),
  Low decimal(18, 5),
  Close decimal(18, 5),
  Volume int
)

Я пытаюсь создать запрос, в котором я могу объединить данные в более высокие периоды времени, например, я хочубыть в состоянии Показывать открытие, максимум, минимум и закрытие для каждого часа.

Ниже мой запрос пока, мне удалось получить максимум и минимум, но как вы получаете открытия и закрытия?

  SELECT MIN(BarTimeStamp) AS TimeStamp,
         MAX(High) AS High,
         MIN(Low) AS Low,
         SUM(Volume) AS Volume
    FROM TimeBar
   WHERE Instrument = 'XYZ'
GROUP BY DATEPART(YEAR, BarTimeStamp), DATEPART(MONTH, BarTimeStamp), DATEPART(DAY, BarTimeStamp), DATEPART(HOUR, BarTimeStamp)

Ответы [ 2 ]

1 голос
/ 22 ноября 2011

Первое, что нужно сделать, это сгруппировать по диапазонам времени:

SELECT MIN(BarTimeStamp) AS StartTimeStamp,
         MAX(BarTimeStamp) AS EndTimeStamp
    FROM #TimeBar
   WHERE Instrument = 'TEST'
GROUP BY DATEPART(YEAR, BarTimeStamp), DATEPART(MONTH, BarTimeStamp), DATEPART(DAY,       BarTimeStamp), DATEPART(HOUR, BarTimeStamp)

После этого необходимо:

  • сделать объединение для получения диапазонов,
  • делает объединение для начала
  • выполняет объединение для получения минимальной
  • группировки по исходному диапазону для выбора всего

Мне нравитсячтобы использовать простые табличные выражения, чтобы упростить задачу:

;WITH times as (
    SELECT MIN(BarTimeStamp) AS StartTimeStamp,
             MAX(BarTimeStamp) AS EndTimeStamp
        FROM #TimeBar
       WHERE Instrument = 'TEST'
    GROUP BY DATEPART(YEAR, BarTimeStamp), DATEPART(MONTH, BarTimeStamp), DATEPART(DAY, BarTimeStamp), DATEPART(HOUR, BarTimeStamp)
)
SELECT 
    StartTimeStamp as TimeStamp
    ,MIN([first].[Open]) as [Open]
    ,MAX(ranged.High) as High
    ,MAX(ranged.Low) as Low
    ,MIN([last].[Close]) as [Close]
    ,SUM(ranged.Volume) as Volume
FROM times 
INNER JOIN #TimeBar ranged ON times.StartTimeStamp <= ranged.BarTimeStamp AND times.EndTimeStamp >= ranged.BarTimeStamp
INNER JOIN #TimeBar [first] ON times.StartTimeStamp = [first].BarTimeStamp 
INNER JOIN #TimeBar [last] ON times.EndTimeStamp = [last].BarTimeStamp 
GROUP BY [times].StartTimeStamp

Вот мои тестовые данные:

CREATE TABLE #TimeBar (
  Instrument varchar(20),
  BarTimeStamp datetimeoffset(7),
  [Open] decimal(18, 5),
  High decimal(18, 5),
  Low decimal(18, 5),
  [Close] decimal(18, 5),
  Volume int
)

insert into #TimeBar values ('TEST', '2011-11-21 1:00', 5, 6, 4, 8, 100)
insert into #TimeBar values ('TEST', '2011-11-21 1:10', 1, 7, 3, 4, 100)
insert into #TimeBar values ('TEST', '2011-11-21 2:10', 15, 16, 17, 18, 100)
insert into #TimeBar values ('TEST', '2011-11-21 2:30', 12, 16, 17, 19, 100)
insert into #TimeBar values ('TEST', '2011-11-21 2:50', 13, 14, 15, 20, 100)

и результат:

TimeStamp                          Open                                    High                                    Low                                     Close                                   Volume
---------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- -----------
2011-11-21 01:00:00.0000000 +00:00 5.00000                                 7.00000                                 4.00000                                 4.00000                                 200
2011-11-21 02:10:00.0000000 +00:00 15.00000                                16.00000                                17.00000                                20.00000                                300

Обратите внимание, яиспользовал временную таблицу для этого, просто измените #TimeBar на TimeBar, чтобы изменить его для вашей реальной таблицы.


Кроме того, я не хотел бы видеть Instrurment varchar в качестве определения поля.Для этого вы должны использовать суррогатный ключ .

1 голос
/ 22 ноября 2011

Используйте основной запрос как подзапрос, для каждой записи берется минимальная временная метка и максимальная временная метка, поэтому для них берутся соответствующие цены открытия и закрытия.

SELECT x.*, TI.Open, TE.Close
FROM
(
SELECT   Instrument,
         MIN(BarTimeStamp) AS TimeStampIni,
         MAX(BarTimeStamp) AS TimeStampEnd,
         MAX(High) AS High,
         MIN(Low) AS Low,
         SUM(Volume) AS Volume
    FROM TimeBar
GROUP BY Instrument, DATEPART(YEAR, BarTimeStamp), DATEPART(MONTH, BarTimeStamp), DATEPART(DAY, BarTimeStamp), DATEPART(HOUR, BarTimeStamp)
) x
inner join TimeBar TI on ti.Instrument = x.Instrument AND TI.BarTimeStamp = x.TimeStampIni
inner join TimeBar Te on te.Instrument = x.Instrument AND Te.BarTimeStamp = x.TimeStampEnd
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...