Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Переписать запрос / 18 сообщений из 18, страница 1 из 1
15.04.2017, 09:48
    #39439058
SqlDreamer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
Довольно распространенная задача, фильтры по входным параметрам (параметры могут быть, а могут и не быть).
Т.е. упрощенно, в наличии две таблицы,
надо вывести все записи из первой таблицы, в привязке ко второй (параметры),
но если во второй записей нет (параметры не заданы), то из первой вывести все записи. Без дин.скл.
Обычно что-то типа такого:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
create table table1
as
select level lvl
  from dual connect by level<1000000;
  
create table table2
as
select cast(null as number) lvl from dual where 1=2;

-- вариант 1
with t2 as (select count(*) cnt from table2)
select t1.*
  from table1 t1, t2
 where t2.cnt = 0
    or (t2.cnt > 0 and t1.lvl in (select lvl from table2 t3));
    
-- вариант 2    
with t2 as (select null lvl 
             from dual
            where 0 = (select count(*) cnt from table2)
            union all
            select lvl from table2)
select t1.*
  from table1 t1, t2
 where t1.lvl = nvl(t2.lvl, t1.lvl);


По сути не сильно отличаются по-моему и вроде работает,
но что-то не нравится (в первом случае каждый раз проверка t2.cnt, во втором NVL)
и ощущение, что можно переписать как-то более изящно что ли.
...
Рейтинг: 0 / 0
15.04.2017, 10:00
    #39439065
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
SqlDreamerДовольно распространенная задача, фильтры по входным параметрам (параметры могут быть, а могут и не быть).
Т.е. упрощенно, в наличии две таблицы,
надо вывести все записи из первой таблицы, в привязке ко второй (параметры),
но если во второй записей нет (параметры не заданы), то из первой вывести все записи.Каждый кулик своёболото считает образцом для подражания.
SqlDreamerОбычно что-то типа такого:Обычно используют bind-ы. А если приложение недо-, то обычно с этого и начинают.
...
Рейтинг: 0 / 0
15.04.2017, 14:09
    #39439119
SqlDreamer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
ElicОбычно используют bind-ы. А если приложение недо-, то обычно с этого и начинают.
Чота вы сегодня не с той ноги, сразу болтом обзываетесь ) между тем действительно встречал немало болот, где используют подобный подход. Бинды конечно есть, по ним и достаются данные в table2, здесь упростил, чтобы отразить суть вопроса.
То есть данные из table2 достаются по биндам, а далее они являются фильтром для table1, но если в table2 ничего не попало, то из table1 надо достать все.
...
Рейтинг: 0 / 0
15.04.2017, 20:25
    #39439185
ora601
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
SqlDreamerТ.е. упрощенно, в наличии две таблицы,
надо вывести все записи из первой таблицы, в привязке ко второй (параметры),
но если во второй записей нет (параметры не заданы), то из первой вывести все записи. Без дин.скл.


LEFT JOIN ?? :)
...
Рейтинг: 0 / 0
16.04.2017, 10:26
    #39439262
SqlDreamer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
ora601LEFT JOIN ?? :)
Типа такого?
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
with t2 as (select lvl 
              from table1
             where 0 = (select count(*) cnt from table2)
             union all
            select lvl from table2)
select t1.*
  from t2, table1 t1
 where t2.lvl = t1.lvl(+);


Но тогда если в table2 нет записей, то джоин как бы вообще не нужен. Выходит, только дин.скл.
...
Рейтинг: 0 / 0
21.04.2017, 17:49
    #39442468
JaRo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
Код: plsql
1.
2.
3.
4.
5.
select lvl from (
select table1.*, table2.lvl t2_lvl, count(table2.lvl) over () cou
from table1, table2
where table1.lvl = table2.lvl(+)
) where cou = 0 or t2_lvl is not null

PS: lvl во второй таблице ведь не может быть null? ну или если может, то это не считается "в привязке ко второй" или как?
...
Рейтинг: 0 / 0
21.04.2017, 18:18
    #39442481
ora601
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
SqlDreamer,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
with t2_cnt AS 

(SELECT COUNT(*) cnt FROM t2)

SELECT t1.* 
FROM t1 LEFT JOIN t2 ON t1.id=t2.id

WHERE t2.id IS NOT NULL OR (SELECT cnt FROM t2_cnt) = 0 
 
...
Рейтинг: 0 / 0
24.04.2017, 14:10
    #39443295
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
SqlDreamer,

ну извратиться конечно можно =)

Код: plsql
1.
2.
3.
select t1.*
from t1, (select nvl(t2.lvl,null) lvl from dual left join t2 on (t2.f= :param/*условие на t2*/)) t3
where t1.lvl = nvl(t3.lvl, t1.lvl)
...
Рейтинг: 0 / 0
24.04.2017, 14:16
    #39443298
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
MaximaXXL,

даже так, точнее:
Код: plsql
1.
2.
3.
select t1.*
from t1, (select t2.lvl from dual left join t2 on (t2.f= :param/*условие на t2*/)) t3
where t1.lvl = nvl(t3.lvl, t1.lvl)



ну в общем мысль понятна ...
...
Рейтинг: 0 / 0
24.04.2017, 14:48
    #39443328
dbms_photoshop
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
MaximaXXLну в общем мысль понятна ...Непонятно только почему ты приплел :param.

Если цель решить задачу ТС с одним проходом каждой из таблиц и без всяких аналитических сортировок,
то это можно (но не нужно) сделать примерно так
Код: plsql
1.
select * from t1 join dual left join t2 on 0 = 0 on t1.id = nvl(t2.id, t1.id)


В 12с вместо нелепого left join можно было бы использовать lateral/outer apply.
...
Рейтинг: 0 / 0
24.04.2017, 16:31
    #39443452
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
dbms_photoshopНепонятно только почему ты приплел :param.
......
В 12с вместо нелепого left join можно было бы использовать lateral/outer apply.

ну это я в шар хрустальный глянул и понял что SqlDreamer будет передавать условия во внутреннюю таблицу и если записей нет то выдать все (так и писал)

по 12с - мы еще на 11 посему outer join пока
...
Рейтинг: 0 / 0
24.04.2017, 16:40
    #39443463
dbms_photoshop
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
MaximaXXL,

Вроде ТС довольно четко объяснил, что если t2 пустая, то выдаются все записи t1, иначе фильтруются по t2.
...
Рейтинг: 0 / 0
24.04.2017, 16:52
    #39443479
Переписать запрос
SqlDreamer,

Код: plsql
1.
select * from t1, t2 where t1.lvl = nvl(t2.lvl,t1.lvl)
...
Рейтинг: 0 / 0
24.04.2017, 16:53
    #39443480
Пардоньте
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
Неужели всё так просто?,

Код: plsql
1.
select t1.* from table1 t1, table2 t2 where t1.lvl = nvl(t2.lvl,t1.lvl)
...
Рейтинг: 0 / 0
24.04.2017, 16:59
    #39443488
dbms_photoshop
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
ПардоньтеНеужели всё так просто?,

Код: plsql
1.
select t1.* from table1 t1, table2 t2 where t1.lvl = nvl(t2.lvl,t1.lvl)

Еще раз для танкистов: если t2 пустая - должны быть возвращены все строки из t1.

Неужели так сложно осилить формулировку из одной строки да еще и при наличии решений?
...
Рейтинг: 0 / 0
24.04.2017, 17:16
    #39443503
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
dbms_photoshop,

:param - это переменная для условия on (t2.f = значение)
Это ни в коем случае не часть аналитической функции

т.е. я выделил место где задавать условие, отлаживался я так =)
...
Рейтинг: 0 / 0
24.04.2017, 17:25
    #39443518
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
dbms_photoshopMaximaXXL,

Вроде ТС довольно четко объяснил, что если t2 пустая, то выдаются все записи t1, иначе фильтруются по t2.

так и было написано, основной момент был указан что делать dual left Join table2 чтоб в случае пустой table2 после наложения условий была хотя-бы одна строка на выходе, значением которой можно управлять посредством nvl(t2.lvl,значение_для_пустой_таблицы). Но посмотрев в условие и увидев что SqlDreamer подходит null я просто заменил nvl(t2.lvl,значение_для_пустой_таблицы) на t2.lvl.

Ваш вариант более предпочтителен в конкретно поставленной задаче, я не спорю
...
Рейтинг: 0 / 0
24.04.2017, 17:34
    #39443526
dbms_photoshop
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переписать запрос
MaximaXXL,

Более предпочтительна здесь скорее всего динамика, с генерацией in (list) вместо t2 по мере необходимости.
Но, я думаю, мы друг друга поняли.
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Переписать запрос / 18 сообщений из 18, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]