SQL - выбор в одной таблице на основе совпадающих значений, приведенных в другой таблице

После бесконечных попыток обработки больших (3-35 ГБ) файлов csv в R я перешел на SQL для обработки этих наборов данных. Итак, я использую этот код в среде R (используя пакет RSQLite на основе SQlite), но он не должен отвлекать от моего вопроса SQL!

Мой вопрос: как мне выбрать одну таблицу на основе совпадающих значений, приведенных в другой таблице?

Хочу пояснить на примере. У меня такой формат таблицы:

Таблица данных

Symbol| Value| EX
A  | 1  | N       
A  | 1  | N     
A  | 2  | T  
A  | 3  | N  
A  | 4  | N  
A  | 5  | N  
B  | 1  | P       
B  | 2  | P  
B  | 2  | N  
B  | 2  | N  
B  | 3  | P  
B  | 5  | P  
B  | 6  | T  
... 

Я хочу выбрать все записи, для которых значение symbol и exchange соответствует определенному условию, приведенному в приведенной ниже таблице.

Таблица Symbolexchange:

Ticker| Exchange
A  | N       
B  | P  
... 

(Обратите внимание, что символ и тикер относятся к одному и тому же атрибуту, также EX и Exchange относятся к одному и тому же атрибуту)

Таким образом, результат, к которому я стремлюсь, таков, чтобы он сохранял только записи A, если обмен равен N и т. Д.:

Symbol| Value| EX
A  | 1  | N       
A  | 1  | N     
A  | 3  | N  
A  | 4  | N  
A  | 5  | N  
B  | 1  | P       
B  | 2  | P  
B  | 3  | P  
B  | 5  | P  
... 

Мне удалось сделать это двумя способами, хотя они меня не совсем устраивают.

Этот метод добавляет справочную таблицу в столбцы рядом с исходной таблицей, которая является избыточной.

SELECT *
FROM Data
INNER JOIN Symbolexchange 
ON Data.EX=Symbolexchange.EXCHANGE
AND Data.SYMBOL=Symbolexchange.TICKER

Этот метод также выполняет работу напрямую, но работает медленнее, чем описанный выше.

SELECT *
FROM Data
WHERE EX=(SELECT exchange FROM Symbolexchange WHERE ticker = SYMBOL)

Есть ли способ лучше и быстрее запрограммировать это? Скорость очень важна из-за размера моих наборов данных. Любые другие комментарии к моему коду приветствуются!

Спасибо


person Hugstime    schedule 30.10.2013    source источник
comment
Второй оператор sql будет соответствовать только EX. Вы этого хотите? Вам не нужно совпадать Symbol и Ticker?   -  person unlimit    schedule 30.10.2013
comment
Да, вы правы, я хочу сопоставить только EX на основе таблицы Symbolexchange. Итак, для тикера A я хочу выбрать только строки, для которых Exchange равен N. Для тикера B я хочу выбрать только строки, для которых Exchange равен P. и т. Д.   -  person Hugstime    schedule 30.10.2013
comment
Два вопроса: 1) что это за СУБД? (рекомендации по производительности сильно различаются для разных таблиц) и 2) Есть ли у вас какие-либо ключи или индексы, определенные для любой из этих таблиц?   -  person RBarryYoung    schedule 30.10.2013
comment
1) SQLite 2) Нет (еще нет? :))   -  person Hugstime    schedule 30.10.2013
comment
Я думаю, что первый sql будет работоспособным. Я не могу сейчас придумать ничего более эффективного. Вы также можете повысить производительность, добавив правильные индексы. Вы можете удалить лишние столбцы, не выполняя Select *, а выполняя Select data.symbol, data.value, data.ex.   -  person unlimit    schedule 30.10.2013


Ответы (2)


Две вещи, которые вы можете сделать, чтобы повысить производительность:

Сначала (и самое главное) добавьте ключ или индекс к своим таблицам. Я не знаю SQLite, но обычно есть такая команда:

CREATE INDEX DataIX1 ON Data(Symbol,EX)

Вам также понадобится один на другом столе:

CREATE INDEX SymbolExchangeIX1 ON Symbolexchange(Ticker,Exchange)

Возможно, вам придется добавить ".." или ".." к именам ...

Во-вторых, хотя ваш первый запрос, вероятно, ваш лучший подход, вы должны возвращать только те столбцы, которые вам действительно нужны / нужны:

SELECT Data.*
FROM Data
INNER JOIN Symbolexchange 
ON Data.EX=Symbolexchange.EXCHANGE
AND Data.SYMBOL=Symbolexchange.TICKER
person RBarryYoung    schedule 30.10.2013
comment
Спасибо! Я рассчитал это в R, и это ускорило мой код с 9,74 секунды до 0,40 секунды для части моих данных. - person Hugstime; 30.10.2013

Я не уверен, используете ли вы mysql или MS SQL. Для MS SQL вы ускоряете свой запрос, добавляя к вашим запросам блокировку без блокировки.

1) С (НЕТ)

Select * from user with (NOLOCK)

OR

2) УСТАНОВИТЬ УРОВЕНЬ ИЗОЛЯЦИИ ПЕРЕДАЧИ, ЧИТАТЬ НЕОБХОДИМО

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
select * from user a, class b where a.userid=b.userid

Вы можете обратиться к ранее обсужденной теме по этому поводу ниже.

person Dillon Tan    schedule 30.10.2013
comment
Это очень плохая идея, и она редко ускоряет запросы, если таблицы спроектированы правильно. - person RBarryYoung; 30.10.2013