"union" и оператор "in" в нижнем блоке исключить то, что вошло в in верхнего блока

alexey.barkalov
Дата: 25.08.2012 12:46:48
Добрый день.
Есть простой запрос, суть которого состоит в том, что перед union'ом выполняется выборка из заданного перечня my_set,
а после union'a происходит выборка только из тех оставшихся элементов множества my_set, которые не вошли в первый подзапрос:

select tbl1.id, tbl1.f2, tbl2.f3
from tbl1
        join tbl2 on tbl1.id in (my_set) and tbl2.f1=tbl1.f2 ...
where ...
union 
select tbl3.f1, tbl3.f2, tbl2.f3
from tbl3
        join tbl2 on tbl3.id in (my_set) and tbl3.id not in (select id from tbl1 where id in (my_set))

где my_set = 1, 2,.., n


Скажите, пожалуйста, можно ли как то у простить данный запрос, не приведет ли строка после union'a
    join tbl2 on tbl3.id in (my_set) and tbl3.id not in (select id from tbl1 where id in (my_set))

к замедлению?
Гаджимурадов Рустам
Дата: 25.08.2012 12:54:36

Ты бред какой-то спрашиваешь.
Ты что такое union и join понимаешь вообще,
чем они отличаются и как (когда) выполняются?

Posted via ActualForum NNTP Server 1.5

alexey.barkalov
Дата: 25.08.2012 13:31:09
Гаджимурадов Рустам
Ты бред какой-то спрашиваешь.
Ты что такое union и join понимаешь вообще,
чем они отличаются и как (когда) выполняются?

абсолютно понимаю.

union - я использую для того, чтобы объединить данные из разных таблиц,
я понимаю, что в данном примере вместо join можно обойтись Where, но
в реальном запросе много join'ов, поэтому в примере его и привел.
Постараюсь объяснить более подробно: пусть my_set это список из
элементов из id (125, 121, 56, 382). Таблица tbl1 имеет записи с id 121, 56,
тогда выборка из tbl3 должна произойти только по id = 125, 382
Dimitry Sibiryakov
Дата: 25.08.2012 13:42:46

alexey.barkalov
Постараюсь объяснить более подробно: пусть my_set это список из
элементов из id (125, 121, 56, 382). Таблица tbl1 имеет записи с id 121, 56,
тогда выборка из tbl3 должна произойти только по id = 125, 382

Когда я вижу такие хитрозавёрнутые условия, у меня всегда закрадывается подозрение о криво
спроектированной БД.
select id from
    (select id from tbl1 union select id from tbl2)
where id in (125, 121, 56, 382)

Posted via ActualForum NNTP Server 1.5

kdv
Дата: 25.08.2012 13:51:30
alexey.barkalov
абсолютно понимаю.
union - я использую для того, чтобы объединить данные из разных таблиц

и что, в обоих объединяемых запросах есть одинаковые записи, которые ты хочешь убрать union-ом?

суть твоего запроса - вначале выполняется один подзапрос, потом второй, потом результаты объединяются.

alexey.barkalov
не приведет ли строка после union'a

это ахинея. возможно, ты имел в виду "не приведет ли второй запрос в union к ..."?

В общем, вначале ты проверяешь скорость всех запросов. Потом объединяешь их через union all. Если лезут дубликаты - используешь union вместо union all. И, наконец, если результат union/union надо отсортировать, добавляешь в конце order by.
alexey.barkalov
Дата: 25.08.2012 13:53:47
Dimitry Sibiryakov
select id from
    (select id from tbl1 union select id from tbl2)
where id in (125, 121, 56, 382)


Дмитрий, спасибо за ответ,
1) но это не то что мне нужно, потому как из таблицы 3 (tbl3)
происходит выборка по только тем id, которые не нашлись в таблице 1 (tbl1).

2)
from tbl3
        join tbl2 on tbl3.id in (my_set) and tbl3.id not in (select id from tbl1 where id in (my_set))

скажи, пожалуйста, как себя будет вести сервер fb 2.0 - здесь select id from tbl1 where id in (my_set)
вызовется всего-лишь один раз или же будет дергаться на каждую запись
alexey.barkalov
Дата: 25.08.2012 14:01:24
kdv
это ахинея. возможно, ты имел в виду "не приведет ли второй запрос в union к ..."?

Да, абсолютно верно.
kdv
Потом объединяешь их через union all

А почему сразу нельзя union - union all работает значительно быстрее?
kdv
если результат union/union надо отсортировать, добавляешь в конце order by.

[/quot]
мне нужно чтобы выборка из таблицы 3 (tbl3) происходила только по тем id,
которые не нашлись в таблице 1 (tbl1).
Dimitry Sibiryakov
Дата: 25.08.2012 14:05:13

alexey.barkalov
1) но это не то что мне нужно, потому как из таблицы 3 (tbl3) происходит выборка по только
тем id, которые не нашлись в таблице 1 (tbl1).

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

Например: tbl1 - умолчательные значения, tbl3 - конкретные значения, которые должны
перекрывать умолчательные.
select coalesce(tbl3.f2, tbl1.f2), coalesce(tbl3.f3, tbl1.f3)
  from tbl1 left join tbl3 on tbl1.id=tbl3.id where tbl1.id in (125, 121, 56, 382)

Posted via ActualForum NNTP Server 1.5

kdv
Дата: 25.08.2012 14:11:55
alexey.barkalov
А почему сразу нельзя union - union all работает значительно быстрее?

union all просто объединяет результаты запросов
union объединяет результаты запросов и затем использует сортировку для поиска и исключения дублирующихся записей.

если у тебя оба объединяемых запроса выдают разные строки, то НИКОГДА нельзя писать union, потому что ты этим заставишь выполнять сервер лишнюю работу, которая ни ему ни тебе не нужна.

p.s. "абсолютно понимаю". :-)
alexey.barkalov
Дата: 25.08.2012 14:26:13
Хорошо сформулирую вопрос по другому:
Есть 3 таблицы: главная (table) имеющая первичное поле pt_id и 2 подчиненные (table_1 и table_2)
имеющее тоже внешнее поле pt_id (ссылка на главную таблицу).
Есть запрос, состоящий из 2-х подзапросов объединенные union all.
Первый из них выбирает данные из table_1, а второй из table_2.
Так вот задача состоит в том, что во втором подзапросе выбирать из table_2 только те записи
pt_id которых не равен тем, которые были выбраны из table_1

Как это сделать?