Наверняка кто-то уже сталкивался с проблемой: как сделать фильтрацию до JOIN-а.
Поясню на примере
есть таблица1:
id (PK) text
1 value
2 meanung
3 word
есть таблица 2
id (FK) param (int)
1 10
3 30
что недо сделать: отфильтровать по значению param в таблице 2 (скажем, <25) и сделать outer join на таблицу 2, т.е. хочу получить такой результат:
1 value 10
2 meaning (null)
Казалось бы, что проще:
Select table1.id, table1.text, table2.param
From table1 left outer join table2 on table1.id = table2.id
Where table2.param < 25
но в результате получается
1 value 10
Причина в том, что выражение Where table2.param < 25 работает после того, как происходи join, и отсеивает строку 2 meaning (null). Как бы это побороть? Сразу хочу предупредить, что вводить какие-то служебные значения в таблицу 2 нежелательно, ввиду того, что по колонке param много условий, и подобрать такое служебное значение, которое завсегда бы попадало во все условия невозможно.
Интересует реализация не для конкретной платформы, а "вообще"
C>Select table1.id, table1.text, table2.param
C>From table1 left outer join table2 on table1.id = table2.id
C>Where table2.param < 25
C>
C>но в результате получается C>
C>1 value 10
C>
C>Причина в том, что выражение Where table2.param < 25 работает после того, как происходи join, и отсеивает строку 2 meaning (null). Как бы это побороть?
Ну, по идее, тебе надо внести это условие внутрь join:
Select table1.id, table1.text, table2.param
From table1 left outer join table2 on table1.id = table2.id and table2.param < 25
... << RSDN@Home 1.1 alpha 1 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Creep, Вы писали:
C>Привет.
C>Наверняка кто-то уже сталкивался с проблемой: как сделать фильтрацию до JOIN-а.
C>Поясню на примере
C>есть таблица1:
C>
C>id (PK) text
C> 1 value
C> 2 meanung
C> 3 word
C>
C>есть таблица 2 C>
C>id (FK) param (int)
C> 1 10
C> 3 30
C>
C>что недо сделать: отфильтровать по значению param в таблице 2 (скажем, <25) и сделать outer join на таблицу 2, т.е. хочу получить такой результат: C>
C>1 value 10
C>2 meaning (null)
C>
C>Казалось бы, что проще:
C>
C>Select table1.id, table1.text, table2.param
C>From table1 left outer join table2 on table1.id = table2.id
C>Where table2.param < 25
C>
C>но в результате получается C>
C>1 value 10
C>
C>Причина в том, что выражение Where table2.param < 25 работает после того, как происходи join, и отсеивает строку 2 meaning (null). Как бы это побороть? Сразу хочу предупредить, что вводить какие-то служебные значения в таблицу 2 нежелательно, ввиду того, что по колонке param много условий, и подобрать такое служебное значение, которое завсегда бы попадало во все условия невозможно. C>Интересует реализация не для конкретной платформы, а "вообще"
можно попробовать вместо From table1 left outer join table2 on table1.id = table2.id использовать
From table1 left outer join (select [id], param from table2 where param < 25 ) as t on table1.id = t.id
или так:
Where table2.param < 25 or table2.param is null
Возможно где-то я и опечатался (т.к. нет времени создавать таблицы и запросы) но принцип должен работать.
Здравствуйте, AntoxaM, Вы писали:
AM>Здравствуйте, Creep, Вы писали:
C>>Наверняка кто-то уже сталкивался с проблемой: как сделать фильтрацию до JOIN-а. C>>
C>>Select table1.id, table1.text, table2.param
C>>From table1 left outer join table2 on table1.id = table2.id
C>>Where table2.param < 25
C>>
AM>возможные варианты: AM>1. AM>
AM>select * from t1 left join t2 on t2.id=t1.id and t2.param <25
AM>
AM>2. AM>
AM>select * from t1 left join (select id from t2 where t2.param <25) as t on t.id=t1.id and
AM>
AM>3. AM>
AM>select * from t1 left join t2 on t2.id=t1.id where t2.param<25 or r2.param is null
AM>
Первый предложенный вариант — то же самое, что и исходный запрос. В третьем — условие "or r2.param is null" никогда не сработает, т.к. null-значений в таблице не хранится, null-овые значения появляются в результате OUTER JOIN-а. Т.е. тоже сводится к первому варианту.
Второй вариант, я подозреваю, работает только ms sql. (насчёт оракла — не знаю). Я, к сожалению, работаю с более древним, можно сказать реликтовым движком, у меня такая фишка не прокатывает...
Здравствуйте, Sinclair, Вы писали:
C>>Причина в том, что выражение Where table2.param < 25 работает после того, как происходи join, и отсеивает строку 2 meaning (null). Как бы это побороть? S>Ну, по идее, тебе надо внести это условие внутрь join: S>
S> Select table1.id, table1.text, table2.param
S> From table1 left outer join table2 on table1.id = table2.id and table2.param < 25
S>
Не будет работать. Таблица приJOINится, а фильтрации реально не произойдёт:
вместо требуемого:
Select table1.id, table1.text, table2.param
From table1 left outer join table2 on table1.id = table2.id
Where not exists (Select * from table2 t3
where table1.id = t3.id and t3.param > 25)
следует обратить внимаение на обращение условия: t3.param > 25.
Здравствуйте, Creep, Вы писали:
C>Не будет работать. Таблица приJOINится, а фильтрации реально не произойдёт: C>вместо требуемого: C>
C>1 value 10
C>2 meaning (null)
C>
C>получим что-то типа: C>
C>1 value 10
C>2 meaning (null)
C>3 word (null)
C>
Все правильно... Как раз фильтрация и происходит, причем в нужном месте..
Сначало отсеиваются все записи из table2 в которых param<25, остается id = 1, param=10.
Далее происходит объединение: Для единственной совпадающей записи после обединения ты получаешь
1 value 10
А потом для каждой записи из table1 которой не находится записи в table2 param заполняется null'ями.
2 meaning (null)
3 word (null)
Все по правилам...
Если бы фильтрации не было то ты бы получил
Здравствуйте, Creep, Вы писали: C>>>Наверняка кто-то уже сталкивался с проблемой: как сделать фильтрацию до JOIN-а.
Все три варианта работают так как вы описывали(фильтрация тбл 2 с последующим outer join'ом в одном запросе) на mssql. Т.к. я не знал что за бд у вас, то я предложил 3 варианта, хоть какой-то должен был заработать.
Другое дело, что, судя по примеру и запросу, который вы написали как правильный, вы хотели несколько другого, поэтому вам не мог подойти ни один из предложенных запросов.
Здравствуйте, Creep, Вы писали:
C>Второй вариант, я подозреваю, работает только ms sql. (насчёт оракла — не знаю). Я, к сожалению, работаю с более древним, можно сказать реликтовым движком, у меня такая фишка не прокатывает...
Нет. не только. Во всех СУБД, где реализованы подзапросы.
Общее для всех СУБД решение будет использование временных таблиц или структур данных.