Как сравнить наблюдения за ценами в скользящих временных интервалах?

#sas #sas-macro #datastep

#sas #sas-макрос #datastep

Вопрос:

Я хотел бы сравнить наблюдения за ценами в скользящем временном окне в 10 минут.

Допустим, у меня есть следующая таблица с ценами (крайний левый столбец) на продукты и временем, в которое они были проданы:

 data have;
input @1 PRICE 1. @6 PRODUCT $3. @12 DATE_TIME anydtdtm15.;
format date_time datetime17.;
datalines;
1    POW   JAN-01-17 13:00
2    POW   JAN-01-17 13:04
1    POW   JAN-01-17 13:06
2    POW   JAN-01-17 13:15
3    POW   JAN-01-17 13:20
5    POW   JAN-01-17 13:29
1    GAS   JAN-01-17 13:05
2    GAS   JAN-01-17 13:10
1    GAS   JAN-01-17 13:39
;;;;
run;
  

Что мне нужно, так это фрагмент кода, который позволит мне сравнивать цены в 10-минутном окне. Например: наблюдение за POW в 13:00 имеет цену 1, и это наблюдение за ценой следует сравнить со всеми другими наблюдениями за ценами до 15: 10, которые относятся к тому же продукту. Если в этом временном окне есть совпадение по цене, соответствующие строки должны быть отображены в таблице.

Это снова нужно сделать для наблюдения в 13: 04 и цены 2, которую затем следует сравнить с наблюдениями до 13: 14 и так далее..

Можно ли это сделать?

Комментарии:

1. Конечно, это можно сделать, но что вы пробовали? Вы получали ошибки, комбинаторные сбои или отсутствующие данные? Почему 10-минутное окно, начинающееся в 13:00, заканчивается в 15: 10?

2. Извините, имел в виду 13:10. Что ж, прямо сейчас я работаю над добавлением 10 минут к дате-времени для каждой строки, а затем объединяю таблицу саму по цене и продукту. Кажется, пока вроде как работает. Хотя выглядит немного неуклюже.

3. Это фактически решило проблему. Мне потребовалось некоторое время, чтобы добраться туда, но я думаю, что теперь я понял это.

Ответ №1:

Было ли ваше решение SQL рефлексивным (или самостоятельным) объединением?

В этом примере self left join строки объединены по продукту и цене, чтобы обеспечить соблюдение одних и тех же критериев поиска цен. Объединение дополнительно ужесточается за счет ограничения временных рамок, в течение которых одни и те же цены принимаются за совпадение. левое соединение используется в случае, если нет будущего с той же ценой.

 data have;
input @1 PRICE 1. @6 PRODUCT $3. @12 DATE_TIME anydtdtm15.;
format date_time datetime17.;
datalines;
1    POW   JAN-01-17 13:00
2    POW   JAN-01-17 13:04
1    POW   JAN-01-17 13:06
2    POW   JAN-01-17 13:15
3    POW   JAN-01-17 13:20
5    POW   JAN-01-17 13:29
1    GAS   JAN-01-17 13:05
2    GAS   JAN-01-17 13:10
1    GAS   JAN-01-17 13:39
1    GAS   JAN-01-17 13:42
1    GAS   JAN-01-17 13:44
1    GAS   JAN-01-17 13:52
;;;;
run;

proc sql;
  create table want as
  select self.*
  , twin.date_time as same_priced_future_date_time
  , twin.date_time - self.date_time as delta format=time8.
  from have as self
  left join have as twin
  on self.product = twin.product
  and self.price = twin.price
  and self.date_time < twin.date_time
  and twin.date_time - self.date_time <= '00:10:00't
  order by self.product, self.date_time, twin.date_time
  ;
  

Существуют другие способы, использующие шаг ДАННЫХ; будь то слияние / задержка, циклы DOW или хэширование

Комментарии:

1. Извините, я не уверен, что означает SQL reflexive. Что я сделал, так это создал новую переменную datetime, которая является исходной datetime плюс 10 минут, а затем объединил набор данных сам по себе в proc sql, где одним из условий для объединения было выражение between (datetime и datetime плюс 10). Это дало мне то сопряжение, которое мне было нужно.

2. присоедините набор данных к самому себе — это рефлексивно :). То же самое have as self left join have as twin в примере выше.