Oracle запрос с разными датами
Я должен написать этот запрос, и он немного сложен. Я надеюсь, что кто-то может помочь, так как я получил большую помощь отсюда раньше.
Скажем, у меня есть портфель клиентов. И список тикеров компании, и дата покупки тикера. Мой список выглядит примерно так:
CYSL 1/16/2017
MCIG 4/1/2016
MSRT 9/13/2016
NTFU 1/16/2017
QNTM 10/30/2014
SIGWX 6/28/2014
TRMCX 6/25/2014
TRT2 4/19/2016
Теперь, чтобы я мог вычислить некоторую производительность с начала года, мне нужно применить следующую логику:
Если дата покупки> 01.01.2017, я буду использовать цену закрытия тикера, когда он был куплен. Если дата покупки < 01.01.2017. Я буду использовать цену закрытия тикера <= 31.12.2016.
Здесь задействованы 2 таблицы: 1) Таблица портфелей 2) История цен
Я получил это далеко:
SELECT ticker, MIN(transaction_date) KEEP (DENSE_RANK FIRST ORDER BY transaction_date) transaction_date
FROM customer_portfolios
WHERE portfolio_id = 954118
GROUP BY ticker;
Это дает мне список выше. Теперь я заблудился о том, как объединить это с логикой выше, чтобы получить правильную дату и пойти по правильной цене.
Я надеюсь, что объясняю это правильно.
И помощь будет отличной, и я могу объяснить больше, если она поможет тебе, помоги мне.
Спасибо.
3 ответа
Использование GREATEST
чтобы получить дату в любом 2016-12-31
или более позднюю дату транзакции, а затем просто присоединитесь к таблице истории цен:
SELECT cp.ticker,
cp.transaction_date,
h.close_price
FROM (
SELECT ticker,
GREATEST(
DATE '2016-12-31',
MIN(transaction_date) KEEP (
DENSE_RANK FIRST
ORDER BY transaction_date
)
) AS transaction_date
FROM customer_portfolios
WHERE portfolio_id = 954118
GROUP BY ticker
) cp
INNER JOIN price_history h
ON ( cp.ticker = h.ticker
AND cp.transaction_date BETWEEN h.start_date AND h.end_date )
или если в истории цен есть строка в день (а не предполагаемый диапазон в запросе выше), то замените последнюю строку на:
AND cp.transaction_date = h.price_date )
Возможно, я что-то здесь упускаю, но без каких-либо реальных образцов данных, это лучшее, что я могу придумать. Ниже приведены таблица ddl's, вставки и запросы и изображение результатов.
CREATE TABLE PRICE_HISTORY
( PRICE_DATE DATE,
TICKER VARCHAR2(20 BYTE),
OPEN_PRICE NUMBER,
CLOSE_PRICE NUMBER
)
CREATE TABLE PORTFOLIO_TABLE
( TICKER VARCHAR2(20 BYTE),
TICKER_DATE VARCHAR2(20 BYTE),
CUSTOMER VARCHAR2(20 BYTE)
)
Insert into PORTFOLIO_TABLE (TICKER,TICKER_DATE,CUSTOMER) values ('CYSL','1/16/2018','1');
Insert into PORTFOLIO_TABLE (TICKER,TICKER_DATE,CUSTOMER) values ('MCIG','04/1/2016','2');
Insert into PORTFOLIO_TABLE (TICKER,TICKER_DATE,CUSTOMER) values ('MSRT','09/13/2016','3');
Insert into PORTFOLIO_TABLE (TICKER,TICKER_DATE,CUSTOMER) values ('NTFU','01/16/2017','4');
Insert into PRICE_HISTORY (PRICE_DATE,TICKER,OPEN_PRICE,CLOSE_PRICE) values (to_date('27-MAR-2017 20:27:12','DD-MON-RRRR HH24:MI:SS'),'CYSL',1,2);
Insert into PRICE_HISTORY (PRICE_DATE,TICKER,OPEN_PRICE,CLOSE_PRICE) values (to_date('16-JUN-1997 20:27:33','DD-MON-RRRR HH24:MI:SS'),'MCIG',1,2);
Insert into PRICE_HISTORY (PRICE_DATE,TICKER,OPEN_PRICE,CLOSE_PRICE) values (to_date('31-MAY-2011 20:27:45','DD-MON-RRRR HH24:MI:SS'),'MSRT',5,8);
Insert into PRICE_HISTORY (PRICE_DATE,TICKER,OPEN_PRICE,CLOSE_PRICE) values (to_date('25-JAN-2021 20:27:55','DD-MON-RRRR HH24:MI:SS'),'NTFU',7,6);
WITH portfolio AS
( SELECT TICKER , TICKER_DATE, CUSTOMER FROM PORTFOLIO_TABLE
)
SELECT
CASE
WHEN PRICE_DATE > '01-JAN-17'
THEN CLOSE_PRICE
ELSE OPEN_PRICE
END AS AMOUNT,
PRICE_DATE,
P.TICKER,
OPEN_PRICE,
CLOSE_PRICE
FROM PRICE_HISTORY H,
PORTFOLIO P
WHERE H.TICKER = P.TICKER;
Конечная цель этого запроса - получить СУММУ портфеля клиентов по его покупкам.
Эта часть работает отлично!
ВЫБЕРИТЕ m_ticker,
GREATEST(ДАТА '2016-12-31', МИН. (Транзакция_дата) СОХРАНИТЬ (
DENSE_RANK ПЕРВЫЙ ЗАКАЗ ПО транзакции_дата)) КАК транзакция_дата ОТ customer_portfolio_history
WHERE portfolio_id = 954118
GROUP BY m_ticker;
Дает мне данные, которые мне нужны:
CYSL 16.01.2017
MCIG 31.12.2016
MSRT 31/12/2016
НТФУ 16.01.2017
QNTM 31.12.2016
SIGWX 31.12.2016
TRMCX 31.12.2016
TRT2 31.12.2016
Теперь становится сложнее. С результатами, приведенными выше, мне нужно перейти в PRICE_HISTORY и найти цену, которая находится на или ближе к (ранее) этой дате.
Таким образом, если нет записи на 31.12.2016 (возможно, рынок был закрыт), попробуйте 12/30, 12/29 и т. Д. То же самое для 16.01.2017. Если нет записи, попробуйте 1/15, затем 1/14....
После этого я могу взять общее количество # акций из таблицы PORTFOLIO для этого клиента / портфеля / тикера и умножить его на цену, которую я получу за найденный день..... и получим значение.
Довольно сумасшедший, я знаю.