Фильтрация до Join-а
От: Creep  
Дата: 08.08.03 07:17
Оценка:
Привет.

Наверняка кто-то уже сталкивался с проблемой: как сделать фильтрацию до 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 много условий, и подобрать такое служебное значение, которое завсегда бы попадало во все условия невозможно.
Интересует реализация не для конкретной платформы, а "вообще"
Re: Фильтрация до Join-а
От: yogi Россия  
Дата: 08.08.03 07:32
Оценка: 1 (1)
Здравствуйте, Creep, Вы писали:

C>Интересует реализация не для конкретной платформы, а "вообще"


Вообще ты можешь джоинить не только таблицы, но и результаты селектов тоже.
Т.е. в твоем случае можно написать примерно так:
select table1.id, table1.text, Tab2.param
from table1 left outer join 
    (select * from table2 where table2.param<25) Tab2
Путь к сердцу женщины лежать не должен.
Re[2]: Фильтрация до Join-а
От: yogi Россия  
Дата: 08.08.03 07:34
Оценка:
Здравствуйте, yogi, Вы писали:

Y>Т.е. в твоем случае можно написать примерно так:

Y>
Y>select table1.id, table1.text, Tab2.param
Y>from table1 left outer join 
Y>    (select * from table2 where table2.param<25) Tab2
Y>


Забыл написать условие джоина Ну да там и так понятно
Путь к сердцу женщины лежать не должен.
Re: Фильтрация до Join-а
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.08.03 07:50
Оценка: 1 (1) +1
Здравствуйте, Creep, Вы писали:


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). Как бы это побороть?

Ну, по идее, тебе надо внести это условие внутрь 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 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Фильтрация до Join-а
От: Renkin Россия  
Дата: 08.08.03 12:01
Оценка:
Здравствуйте, 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

Возможно где-то я и опечатался (т.к. нет времени создавать таблицы и запросы) но принцип должен работать.
Re: Фильтрация до Join-а
От: AntoxaM  
Дата: 08.08.03 12:24
Оценка: 1 (1)
Здравствуйте, 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>

возможные варианты:
1.
select * from t1 left join t2 on t2.id=t1.id and t2.param <25

2.
select * from t1 left join (select id from t2 where t2.param <25) as t on t.id=t1.id and

3.
select * from t1 left join t2 on t2.id=t1.id where t2.param<25 or r2.param is null
Re[2]: Фильтрация до Join-а
От: AntoxaM  
Дата: 08.08.03 12:37
Оценка: -1
Здравствуйте, AntoxaM, Вы писали:
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>

здесь маленькая неточность. проверять на null лучше не t2.param, а t2.id, если t2.param допускает значение null
Re[2]: Фильтрация до Join-а
От: Creep  
Дата: 11.08.03 07:05
Оценка:
Здравствуйте, 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. (насчёт оракла — не знаю). Я, к сожалению, работаю с более древним, можно сказать реликтовым движком, у меня такая фишка не прокатывает...
Re[2]: Фильтрация до Join-а
От: Creep  
Дата: 11.08.03 07:12
Оценка:
Здравствуйте, 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ится, а фильтрации реально не произойдёт:
вместо требуемого:
1     value     10
2     meaning   (null)


получим что-то типа:
1     value     10
2     meaning   (null)
3     word      (null)


:^(
Re[2]: Фильтрация до Join-а
От: Creep  
Дата: 11.08.03 07:17
Оценка:
Здравствуйте, AntoxaM, Вы писали:

AM>Здравствуйте, Creep, Вы писали:


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>


Второй вариант не работает. Получается то же что и в моём ответе Синклеру
Короче, задача в лоб по ходу не решается, я её решил по-другому...

Всем спасибо.
Re[3]: Фильтрация до Join-а
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.08.03 07:29
Оценка:
Здравствуйте, 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>


C>:^(

Ну, тогда надо все же уточнить, что ты имел в виду под outer join. Результат-то правильный! left outer возвращает ВСЕ строки левой таблицы.
... << RSDN@Home 1.1 alpha 1 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Фильтрация до Join-а - solution
От: Creep  
Дата: 11.08.03 07:32
Оценка:
Вот верное решение:

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.
Re[3]: Фильтрация до Join-а
От: Merle Австрия http://rsdn.ru
Дата: 11.08.03 07:33
Оценка:
Здравствуйте, 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)

Все по правилам...
Если бы фильтрации не было то ты бы получил
2     meaning   (null)
3     word      30
Мы уже победили, просто это еще не так заметно...
Re[3]: Фильтрация до Join-а
От: AntoxaM  
Дата: 18.08.03 10:16
Оценка:
Здравствуйте, Creep, Вы писали:
C>>>Наверняка кто-то уже сталкивался с проблемой: как сделать фильтрацию до JOIN-а.

Все три варианта работают так как вы описывали(фильтрация тбл 2 с последующим outer join'ом в одном запросе) на mssql. Т.к. я не знал что за бд у вас, то я предложил 3 варианта, хоть какой-то должен был заработать.
Другое дело, что, судя по примеру и запросу, который вы написали как правильный, вы хотели несколько другого, поэтому вам не мог подойти ни один из предложенных запросов.
Re[3]: Фильтрация до Join-а
От: King Oleg Украина http://kingoleg.livejournal.com
Дата: 18.08.03 11:25
Оценка:
Здравствуйте, Creep, Вы писали:

C>Второй вариант, я подозреваю, работает только ms sql. (насчёт оракла — не знаю). Я, к сожалению, работаю с более древним, можно сказать реликтовым движком, у меня такая фишка не прокатывает...

Нет. не только. Во всех СУБД, где реализованы подзапросы.
Общее для всех СУБД решение будет использование временных таблиц или структур данных.
... << RSDN@Home 1.1 beta 1 >>
King Oleg
*Читайте DOC'и, они rules*
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.