2009-06-14 2 views
2

У меня есть 2 таблицы (?):комплекс SQL присоединиться запрос

1 таблица) Masterdates, который содержит все даты с 1 января, 1900

2) таблица Stockdata, которая содержит данные о запасах в дату форме , символ, открытый, высокий, низкий, близкий, объем (первичный ключ = дата, символ)

Это то, что я ищу, чтобы получить (представленные здесь в формате CSV)

MDate, SDATE, Symbol, Open , Высокий, ...

6/4/2001,6/4/2001, Foo, 47,49, ...

6/5/2001, NULL, NULL, NULL, NULL, ...

6/6/2001,6/6/2001, Foo, 54,56, ...

где MDate от Masterdates и SDate от Stockdata. Мне нужно, чтобы выход начинался с первой (самой ранней) даты окончания для желаемого символа (в этом примере, Foo, начиная с 6/4/2001) в Stockdata, а затем включать все даты в Masterdates до и включая последние (последней) доступной даты для желаемого символа в Stockdata, выводя нули, где нет соответствующей записи Stockdata для данной записи Masterdate в описанном диапазоне.

Есть ли способ сделать это в одном запросе, серию запросов и/или добавлении вспомогательных таблиц, что даст быстрые результаты? Или мне придется выгружать надмножества того, что я хочу, а затем строить окончательный вывод с помощью моего (не-SQL) языка программирования?

ТИА

+0

Какая система SQL точно? MS SQL Server? MySQL? –

ответ

7

Испытано в sqlite3, ваша реализация БД может отличаться

SELECT m.date, 
     s.symbol, 
     s.open, 
     s.high, 
     s.low, 
     s.close, 
     s.volume 
FROM  masterdate AS m LEFT OUTER JOIN 
     stockdata AS s ON m.date = s.date 
AND  s.symbol = 'Foo' 
WHERE m.date >= (SELECT MIN(date) FROM stockdata WHERE symbol = 'Foo') 
AND  m.date <= (SELECT MAX(date) FROM stockdata WHERE symbol = 'Foo') 

Если это не выполняется достаточно Quicky, то вы могли бы pronably повысить производительность за счет установки переменных для минимального и максимального значения в одном запросе и затем используйте те, которые указаны в основном запросе. Это сэкономит вам хотя бы один индексный хит.

Так (В SQL Server Синтаксис)

SET @symbol = 'Foo' 

SELECT @mindate = MIN(date), 
     @maxdate = MAX(date) 
FROM stockdata 
WHERE stockdata.symbol = @symbol 


SELECT m.date, 
     s.symbol, 
     s.open, 
     s.high, 
     s.low, 
     s.close, 
     s.volume 
FROM  masterdate AS m LEFT OUTER JOIN 
     stockdata AS s ON m.date = s.date 
AND  s.symbol = @symbol 
WHERE m.date BETWEEN @mindate AND @maxdate 

Вы также должны быть уверены, что у вас есть индекс по masterdate.date и композитный индекс stockdata (дата, символ).

+0

22 секунды на бит 6 ГБ. Быстрее, чем я думал, это будет, но не там, где мне это нужно. Я думаю, что если я вырву данные, я могу починить их до чего-то гораздо лучшего (в настоящее время у меня есть ежедневный, внутридневный, фондовый, фьючерсный, индекс, вы называете его, данные в одной таблице). Спасибо! – user119282

1

Если вы используете SQLServer, вы можете использовать хранимую процедуру TSQL, чтобы вернуть результаты. Он должен будет в основном две линии:

1) Для того, чтобы получить первую дату имеющихся данных 2) Запрос с внешним соединением

Если вы используете Oracle, вы можете использовать PL/SQL, чтобы написать подобные (хотя и немного сложнее) хранимой процедуры для вычисления требуемого ответа.

3

Это классический левое соединение:

SELECT * FROM masterdates 
    LEFT JOIN stockdata ON masterdates.date = stockdata.date;

Очевидно, что это должно быть уточнено, чтобы возвращать только необходимые столбцы.

+0

Но это все-таки даст мне все в Masterdates, нет? – user119282

0

Я бы предложил заполнить недостающие записи из таблицы Stockdata и использовать внутреннее соединение.Должно быть намного быстрее.

+0

Не могли бы вы объяснить это немного больше? – user35443

Смежные вопросы