#sql-server #tsql #stockquotes
#sql-server #tsql #котировки акций
Вопрос:
У меня есть таблица цен на акции, и мне нужно получить цены за 1-й день каждой недели. Этот SQL в предложении WHERE работает хорошо,
DATEADD(ww, DATEDIFF(ww,0,PriceDt), 0)
за исключением случаев, когда рынок закрыт в понедельник. День труда — хороший пример. Я думал, что использование COALESCE даст мне цену во вторник, если он будет недоступен в понедельник, но это не сработало.
coalesce(DATEADD(ww, DATEDIFF(ww,0,PriceDt), 0), DATEADD(ww, DATEDIFF(ww,0,PriceDt), 1)).
Может кто-нибудь помочь с этим?
declare @t table (PriceDt datetime, Symbol nvarchar(10), OpenPric float, ClosePrice float)
insert @t values ('2010-08-02 00:00:0.000', 'SYM', 15.00, 15.10)
insert @t values ('2010-08-09 00:00:00.000', 'SYM', 15.00, 15.10)
insert @t values ('2010-08-16 00:00:00.000', 'SYM', 15.00, 15.10)
insert @t values ('2010-08-23 00:00:00.000', 'SYM', 15.00, 15.10)
insert @t values ('2010-08-30 00:00:00.000', 'SYM', 15.00, 15.10)
insert @t values ('2010-09-07 00:00:00.000', 'SYM', 15.00, 15.10)
insert @t values ('2010-09-13 00:00:00.000', 'SYM', 15.00, 15.10)
insert @t values ('2010-09-20 00:00:00.000', 'SYM', 15.00, 15.10)
insert @t values ('2010-09-27 00:00:00.000', 'SYM', 15.00, 15.10)
select * from @t
where PriceDt = coalesce(DATEADD(ww, DATEDIFF(ww,0,PriceDt), 0), DATEADD(ww, DATEDIFF(ww,0,PriceDt), 1))
(в результате отсутствует 2010-09-07 00:00:00.000)
2010-08-02 00:00:00.000 SYM 15 15.1 2010-08-09 00:00:00.000 SYM 15 15.1 2010-08-16 00:00:00.000 SYM 15 15.1 2010-08-23 00:00:00.000 SYM 15 15.1 2010-08-30 00:00:00.000 SYM 15 15.1 2010-09-13 00:00:00.000 SYM 15 15.1 2010-09-20 00:00:00.000 SYM 15 15.1 2010-09-27 00:00:00.000 SYM 15 15.1
Комментарии:
1. Если вы делаете подобные вещи все время. Я бы настоятельно рекомендовал создать таблицу календаря, если это возможно. Для этого уже есть сценарии. Таблица может включать в себя такие вещи, как isHoldiay, квартал, будни, выходные и т.д. Значительно упрощает выполнение таких задач.
2. Какой сервер СУБД? SQL Server / Sybase ASE ? Какая версия (
SELECT @@VERSION
) ?3. Вы определенно не можете использовать здесь функцию COALESCE, потому что первый день недели из DATEADD(ww, DATEDIFF(ww,0,PriceDt), 0) не будет равен null . Вам нужен еще один столбец, чтобы решить, когда брать первый день недели, а когда на следующий день, возможно, праздничный стол
4. таблица календаря, как предлагает JChao, — это правильный путь.
Ответ №1:
Это даст вам самую раннюю дату, которая существует в таблице для каждой недели (при условии, что ваша неделя начинается в понедельник):
select min(Pricedt) Pricedt
from @t
group by DATEADD(ww, DATEDIFF(ww,0,PriceDt), 0)
Теперь вы можете просто присоединить этот результат к своей таблице, чтобы получить цены на любой первый день недели, в который введены данные:
select t.Pricedt, t.Symbol, t.OpenPric, t.ClosePrice
from
(
select min(Pricedt) Pricedt
from @t
group by DATEADD(ww, DATEDIFF(ww,0,PriceDt), 0)
) d
join @t t on d.Pricedt = t.PriceDt