SQL-запрос: как перевести IN () в JOIN? - PullRequest
3 голосов
/ 06 апреля 2010

У меня много SQL-запросов, таких как:

SELECT o.Id, o.attrib1, o.attrib2 
  FROM table1 o 
WHERE o.Id IN (
                SELECT DISTINCT Id 
                  FROM table1
                     , table2
                     , table3 
                 WHERE ...
               )

Эти запросы должны выполняться на разных движках базы данных (MySql, Oracle, DB2, MS-Sql, Hypersonic), поэтому я могу использовать только общий синтаксис SQL.

Здесь Я читал, что с MySql оператор IN не оптимизирован и он действительно медленный, поэтому я хочу переключить его на JOIN.

Я пытался:

SELECT o.Id, o.attrib1, o.attrib2 
  FROM table1 o, table2, table3 
  WHERE ...

Но это не учитывает ключевое слово DISTINCT.

Вопрос: Как избавиться от дублирующихся строк, используя подход JOIN?

Ответы [ 4 ]

4 голосов
/ 06 апреля 2010

Чтобы написать это с помощью JOIN, вы можете использовать внутреннее выделение и присоединиться к нему:

SELECT o.Id, o.attrib1, o.attrib2 FROM table1 o
JOIN (
  SELECT DISTINCT Id FROM table1, table2, table3 WHERE ...
) T1
ON o.id = T1.Id

Я не уверен, что это будет намного быстрее, но, может быть ... вы можете попробовать это сами.

В целом, ограничиваясь только SQL, который будет работать с несколькими базами данных, это не приведет к лучшей производительности.

2 голосов
/ 06 апреля 2010

Но это не учитывает ключевое слово DISTINCT.

Вам не нужно distinct в подзапросе. in вернет одну строку во внешнем запросе независимо от того, соответствует ли она одной или ста строкам в подзапросе. Так что, если вы хотите повысить производительность запроса, неплохо было бы начать с distinct.

Один из способов настройки предложений in - переписать их, используя exists. В зависимости от распределения данных это может быть намного эффективнее или медленнее. С тюнингом эталоном является король.

SELECT o.Id, o.attrib1, o.attrib2 
FROM table1 o 
WHERE EXISTS (
  SELECT  Id FROM table1 t1, table2 t2, table3 t3 WHERE ... 
  AND  ( t1.id = o.id 
         or t2.id = o.id 
         or t3.id = o.id 
)

Не зная вашей бизнес-логики, точная формулировка этого дополнительного фильтра может быть неправильной.

Кстати, я заметил, что у вас есть table1 как во внешнем запросе, так и во вложенном запросе. Если это не ошибка в переводе вашего фактического SQL сюда, вы можете подумать, имеет ли это смысл. Было бы лучше не запрашивать эту таблицу дважды; использование exists облегчает избежание двойного удара.

0 голосов
/ 06 апреля 2010

Я не уверен, что действительно понимаю, в чем твоя проблема. Почему бы вам не попробовать это:

SELECT distinct o.Id, o.attrib1, o.attrib2
FROM
table1 o
, table o1
, table o2
...
where
o1.id1 =  o.id
or o2.id = o.id
0 голосов
/ 06 апреля 2010
SELECT DISTINCT o.Id, o.attrib1, o.attrib2 
  FROM table1 o, table2, table3 
 WHERE ...

Хотя, если вам необходимо поддерживать несколько различных серверных баз данных, вы, вероятно, захотите предоставить каждому своему набору классов репозитория на уровне данных, чтобы вы могли оптимизировать свои запросы для каждого. Это также дает вам возможность сохраняться в других типах баз данных, или в xml, или в веб-сервисах, или в любом другом случае, если в будущем возникнет необходимость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...