Оператор SQL для запроса MS Access для расчета квартального темпа роста

У меня есть таблица с именем «Historical_Stock_Prices» в базе данных MS Access. В этой таблице есть столбцы: Ticker, Date1, Open1, High, Low, Close1, Volume, Adj_Close. Строки состоят из данных для каждого тикера за каждый рабочий день.

Мне нужно запустить запрос из моей программы VB.net, который вернет таблицу в моей программе, которая отображает темпы роста для каждого квартала каждого года для каждого перечисленного символа тикера. Так что для этого примера мне нужно найти темпы роста GOOG в 4-м квартале 2012 года.

Чтобы рассчитать это вручную, мне нужно разделить цену закрытия в последний БИЗНЕС-день 4-го квартала (31.12.2012) на цену открытия первого БИЗНЕС-дня 4-го квартала (1.10.2012). Затем мне нужно вычесть на 1 и умножить на 100, чтобы получить процент.

Фактический расчет будет выглядеть так: ((707,38/759,05)-1)*100 = -6,807%

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

Я не могу придумать правильный синтаксис для оператора SQL для создания таблицы темпов роста из таблицы необработанных исторических цен. Может ли кто-нибудь помочь мне со статусом SQL?


person gromit1    schedule 17.09.2013    source источник


Ответы (1)


Вот как бы я подошел к проблеме:

Я бы начал с создания сохраненного запроса Access с именем [Stock_Price_with_qtr], который вычисляет год и квартал для каждой строки:

SELECT 
    Historical_Stock_Prices.*, 
    Year([Date1]) AS Yr, 
    Switch(Month([Date1])<4,1,Month([Date1])<7,2,Month([Date1])<10,3,True,4) AS Qtr
FROM Historical_Stock_Prices

Затем я создал еще один сохраненный запрос в Access с именем [Qtr_Dates], который находит первый и последний рабочие дни для каждого тикера и квартала:

SELECT 
    Stock_Price_with_qtr.Ticker, 
    Stock_Price_with_qtr.Yr, 
    Stock_Price_with_qtr.Qtr, 
    Min(Stock_Price_with_qtr.Date1) AS Qtr_Start, 
    Max(Stock_Price_with_qtr.Date1) AS Qtr_End
FROM Stock_Price_with_qtr
GROUP BY 
    Stock_Price_with_qtr.Ticker, 
    Stock_Price_with_qtr.Yr, 
    Stock_Price_with_qtr.Qtr

Это позволило бы мне использовать следующий запрос в VB.NET (или C#, или самом Access) для расчета квартальных темпов роста:

SELECT 
    Qtr_Dates.Ticker, 
    Qtr_Dates.Yr, 
    Qtr_Dates.Qtr, 
    (([Close_Prices]![Close1]/[Open_Prices]![Open1])-1)*100 AS Qtr_Growth
FROM 
    (
        Historical_Stock_Prices AS Open_Prices 
        INNER JOIN Qtr_Dates 
        ON (Open_Prices.Ticker = Qtr_Dates.Ticker) 
            AND (Open_Prices.Date1 = Qtr_Dates.Qtr_Start)
    ) 
    INNER JOIN 
    Historical_Stock_Prices AS Close_Prices 
    ON (Qtr_Dates.Ticker = Close_Prices.Ticker)
        AND (Qtr_Dates.Qtr_End = Close_Prices.Date1) 
person Gord Thompson    schedule 18.09.2013
comment
Хорошо!! Я попытался поместить все три запроса в Access. Первые два вошли без проблем. Последний запрос выдает ошибку, которая говорит о синтаксической ошибке в выражении SQL. - person gromit1; 18.09.2013
comment
@ nordeen1 Проверьте свой последний запрос на опечатки. Я просто скопировал и вставил последний запрос из своего ответа как в Access 2010, так и в C# 2010 Express, и в каждом случае запрос работал нормально. - person Gord Thompson; 19.09.2013
comment
Это не будет работать в Access или VB.net. Я также скопировал и вставил запросы из вашего ответа в Access и получил ошибку. Я тоже проверил на опечатки и не нашел. Теперь я попытался поместить последний запрос в свою программу, и он дал мне ошибку. Механизм базы данных Microsoft Jet не может найти входную таблицу или запрос Qtr_Dates. Убедитесь, что он существует и его имя написано правильно. Я проверил, и мои запросы помечены Qtr_Dates и Stock_Price_with_qtr. - person gromit1; 19.09.2013
comment
Вот оператор SQL, который я использовал в своем коде Dim da As OleDbDataAdapter = New OleDbDataAdapter("SELECT Qtr_Dates.Ticker, Qtr_Dates.Yr, Qtr_Dates.Qtr, (([Close_Prices]![Close1]/[Open_Prices]![Open1])-1)*100 AS Qtr_Growth FROM (Historical_Stock_Prices AS Open_Prices INNER JOIN Qtr_Dates ON (Open_Prices.Ticker = Qtr_Dates.Ticker) AND (Open_Prices.Date1 = Qtr_Dates.Qtr_Start)) INNER JOIN Historical_Stock_Prices AS Close_Prices ON (Qtr_Dates.Ticker = Close_Prices.Ticker) AND (Qtr_Dates.Qtr_End = Close_Prices.Date1)", Nordeen_Investing_3.con) - person gromit1; 19.09.2013
comment
@ nordeen1 Вы ввели первые два запроса в Access и сохранили их в Access (используя точные имена, указанные в последнем запросе)? - person Gord Thompson; 19.09.2013
comment
Да, они сохранены, и я считаю, что имена указаны правильно. На самом деле я использую OpenOffice на этом компьютере, так что это может быть проблемой. Мне придется переключить компьютеры, чтобы использовать Access, но у меня не было проблем с использованием OpenOffice вместо Access до этого момента с моей программой. Можно ли создать и сохранить первые два запроса из моей программы? Спасибо! - person gromit1; 19.09.2013
comment
@ nordeen1 re: Можно ли создать и сохранить первые два запроса из моей программы? - Да, вы можете использовать DDL для создания сохраненных запросов в базе данных Access из вашего приложения VB.NET. Просто используйте объект OleDbCommand для выполнения CREATE VIEW Stock_Price_with_qtr AS SELECT Historical_Stock_Prices.*, .... - person Gord Thompson; 19.09.2013
comment
Я переключился на Access вместо OpenOffice, и все отлично заработало! Я отметил ваш первоначальный ответ как правильный ответ. Теперь я буду работать над созданием запросов из моей программы, чтобы учесть отсутствие у меня доступа к Microsoft Access. У меня есть один небольшой вопрос о форматировании окончательного запроса. Прямо сейчас окончательный запрос отображает столбцы Ticker, Year, Qtr, Qtr_Growth. И строка для каждого квартала для каждого года каждого тикера. Я хотел бы отобразить эту таблицу в своей программе в виде столбцов 2013-1, 2012-4, 2012-3 и только одной строки для каждого тикера. Спасибо! - person gromit1; 20.09.2013
comment
@ nordeen1 Вы можете создать перекрестный запрос (PIVOT), чтобы получить результаты последнего запроса и переформатировать их, как вы описали. Подход будет аналогичен моему ответу здесь. Если вам нужна помощь в этом, пожалуйста, откройте новый вопрос. - person Gord Thompson; 21.09.2013
comment
Первые два запроса отлично работают в моей программе. Я получаю сообщение об ошибке, когда копирую и вставляю этот оператор SQL для последнего запроса SELECT Qtr_Dates.Ticker, Qtr_Dates.Yr, Qtr_Dates.Qtr, (([Close_Prices]![Close1]/[Open_Prices]![Open1])-1)*100 AS Qtr_Growth FROM (Historical_Stock_Prices AS Open_Prices INNER JOIN Qtr_Dates ON (Open_Prices.Ticker = Qtr_Dates.Ticker) AND (Open_Prices.Date1 = Qtr_Dates.Qtr_Start)) INNER JOIN Historical_Stock_Prices AS Close_Prices ON (Qtr_Dates.Ticker = Close_Prices.Ticker) AND (Qtr_Dates.Qtr_End = Close_Prices.Date1)", Nordeen_Investing_3.con) - person gromit1; 24.09.2013
comment
Это ошибка Additional information: Cannot join on Memo, OLE, or Hyperlink Object (Open_Prices.Ticker=Qtr_Dates.Ticker And Open_Prices.Date1=Qtr_Dates.Qtr_Start). - person gromit1; 24.09.2013
comment
Если [Ticker] является полем Memo, вам придется изменить его на Text. - person Gord Thompson; 24.09.2013
comment
[Тикер] создается с помощью этой строки кода. Я не верю, что это поле Memo. Dim cmd As New OleDb.OleDbCommand("CREATE TABLE " & tblName & "(Ticker Text NOT NULL, Date1 Date NOT NULL, Open1 Money, High Money, Low Money, Close1 Money, Volume Long, Adj_Close Money, CONSTRAINT pk_TickerDate PRIMARY KEY (Ticker, Date1));", Nordeen_Investing_3.con) - person gromit1; 24.09.2013
comment
Ticker Text NOT NULL, вполне может создать поле Memo, поскольку оно не определяет максимальную длину. Ticker Text(10) NOT NULL, (или аналогичный) может работать лучше. - person Gord Thompson; 24.09.2013
comment
Отлично ответил! Спасибо! - person gromit1; 25.09.2013