суббота, 12 января 2013 г.

Использование подзапросов в ORACLE

Типы подзапросов:

Однострочные
возвращают 0 или 1 строку
(если к тому же возвращается и один столбец то подзапрос скалярный)

Многострочные
возвращают одну или несколько строк

Подзапросы можно еще разделить на подтипы:

многостолбцовые

корелированные
(ссылаются на один или несколько столбцов во внешнем запросе)

вложенные
(помещены внутрь другого  подзапроса, уровень вложенности может достигать 255)


Однострочные подзапросы.

Подзапросы во фразе WHERE:

select col1, col2
from tab
where col_tab_id = (select col_tab_id
                    from tab
                    where col2 = 'XXX');

Во фразе WHERE  можно использовать операторы сравнения такие как:
=, <>, <, >, <=, >=

select col1, col2, col3
from tab
where col3 > (select avg(col3)
              from tab);

этот подзапрос является примером скалярного подзапроса.


Подзапросы во фразе HAVING:

select col1, avg(col2)
from tab
group by col1
having avg(col2) <  (select max(avg(col2))
                     from tab
                     group by col1)
order by col1;


Подзапросы во фразе FROM:
(встроенные представления)


select col1
from (select col1
      from tab
      where col1 < 10);


более полезный пример:

select t1.col_tab1_id, col2, t2.COL_TAB1_ID_COUNT
from tab1 t1, (select col_tab1_id, count(col_tab1_id) COL_TAB1_ID_COUNT
               from tab2
               group by col_tab1_id) t2
where t1.col_tab1_id =  t2.col_tab1_id;


Подзапросы не могут содержать фразу order by.
Любое упорядочивание должно проводиться во внешнем запросе:

select col1, col2, col3
from tab
where col3 > (select avg(col3) from tab)
order by col1 desc;

Многострочные подзапросы
Возвращают во внешний запрос одну или более строк.

Чтобы обработать подзапрос, возвращающий несколько строк, необходимо использовать один из операторов:
IN, ANY или ALL.

select col1, col2
from tab
where col1 IN (5,6,7);

Использование IN в многострочных подзапросах:

select col1, col2
from tab
where col1 IN (select col1
                from tab
                where col2 like '_z%');


select col1, col2
from tab1
where col1 NOT IN (select col1 from tab2 );


Использование ANY в многострочных подзапросах:

ANY используется для сравнения значения с любым значением в списке.
Перед ANY можно использовать операторы сравнения такие как:
=, <>, <, >, <=, >=

select col1, col2
from tab1
where col3 < ANY (select col1 from tab2 );


Использование ALL в многострочных подзапросах:

ALL используется для сравнения значения со всеми значениями из списка.
Перед ALL можно использовать операторы сравнения такие как:
=, <>, <, >, <=, >=

select col1, col2
from tab1
where col3 > ALL (select col1 from tab2 );


Многостолбцовые подзапросы:

Подзапросы могут возвращать несколько столбцов:

select col1, col2, col3
from tab1
where (col1, col3) IN
      (select col1, min(col3)
       from tab1
       group by col2);


Коррелированные подзапросы

Коррелированный подзапрос выполняется по одному разу для каждой строки внешнего запроса.
Коррелированный подзапрос может разрешать значения NULL.

Обычно коррелированный подзапрос используется когда мы хотим узнать некую зависимость
от значения в каждой строке внешнего запроса.

select col1, col2, col3, col4
from tab out
where col4 > (select avg(col4) from tab inn
              where inn.col2 = out.col2);

тут строки внешнего запроса по очереди передаются в подзапрос.


Использование EXISTS и NOT EXISTS с коррелированными подзапросами.

EXISTS используется для проверки, существует ли хоть одна строка, возвращенная подзапросом.
NOT EXISTS проверяет что не существует ни одной строки, возвращенной подзапросом.

select col1, col2
from tab out
where EXISTS (select col1 from tab inn
              where inn.col3 = out.col1);

не важно сколько строк возвращает подзапрос,
важно знать, возвращаются ли в принципе какие либо строки.

Подзапрос не обязян возвращать столбец, можно возвратить литеральное значение,
что повысит производительность:

select col1, col2
from tab out
where EXISTS (select 1 from tab inn
              where inn.col3 = out.col1);


до тех пор, пока подзапрос возвращает одну или более строк
EXISTS возвращает TRUE.

если подзапрос не возвращает ни одной строки
EXISTS возвращает FALSE.

Использование NOT EXISTS с коррелированными подзапросами.

select col1, col2
from tab1 out
where NOT EXISTS (select 1 from tab2 inn
                  where inn.col1 = out.col1);


Отличие EXISTS от IN

EXISTS проверяет только сам факт существования строк
IN проверяет их реальные значения
EXISTS более производительные оператор чем IN
Если в списке значений есть NULL, то NOT EXISTS возвратит TRUE, а NOT IN - FALSE.

select col1, col2
from tab1 out
where NOT EXISTS (select 1 from tab2 inn
                  where inn.col1 = out.col1);


select col1, col2
from tab1
where NOT IN (select col1 from tab2);

Разрешить NULL можно так:

select col1, col2
from tab1
where NOT IN (select nvl(col1,0) from tab2);

Вложенные подзапросы:

максимальная глубина вложенности - 255
Лучше использовать соединения чем вложенность.
Глубокая вложенность влияет на производительность.

select col1, avg(col2)
from tab1
group by col1
having avg(col2) < (select max(avg(col1))
                    from tab1
                    where col1 IN (select col1 from tab2 where col2 > 1)
                    group by col1)
order by col1;


UPDATE и DELETE c подзапросами:

update tab1 set col1 = (select avg(col1) from tab2)
where col2 = 4;

delete from tab1
where col1 > (select avg(col1) from tab2);


2 комментария:

  1. SELECT emp.empno, sq.deptno FROM emp, (SELECT deptno FROM dept ORDER BY deptno) sq WHERE emp.deptno = sq.deptno;
    Вот тут уживается ORDER BY внутри подзапроса

    ОтветитьУдалить
  2. ВСЕ ПРОЧИТАЙТЕ НАСТОЯЩЕЕ ОТЗЫВ О том, КАК Я ПОЛУЧИЛ СВОЙ КРЕДИТ ОТ КОМПАНИИ LEGIT И ДОВЕРЕННОЙ КРЕДИТНОЙ СРЕДИ Меня зовут Kjerstin Lis, я искал кредит для погашения своих долгов, все, кого я встречал, мошенничали и брали свои деньги, пока я наконец не встретил мистера Бенджамина Брейл Ли Он смог дать мне кредит в размере 450 000 рублей. Он также помог другим моим коллегам. Я говорю как самый счастливый человек во всем мире сегодня, и я сказал себе, что любой кредитор, который спасает мою семью от нашей бедной ситуации, я скажу имя всему миру, и я так счастлив сказать, что моя семья вернулся навсегда, потому что я нуждался в кредите, чтобы начать свою жизнь заново, потому что я одинокая мама с 3 детьми, и весь мир, казалось, висел на мне, пока я не имел в виду, что БОГ послал ссудодателя, который изменил мою жизнь и член моей семьи, БОЖИЙ кредитор, мистер Бенджамин, он был Спасителем БОГом, посланным для спасения моей семьи, и сначала я подумал, что это будет невозможно, пока я не получу кредит, я пригласил его к себе в семью -все вечеринка, от которой он не отказался, и я посоветую всем, кто действительно нуждается в кредите, связаться с г-ном Бенджамином Брейлом Ли по электронной почте (lfdsloans@outlook.com), потому что он самый понимающий и добрый кредитор. когда-либо встречал с заботливым сердцем. Он не знает, что я делаю это, распространяя свою добрую волю ко мне, но я чувствую, что должен поделиться этим со всеми вами, чтобы освободить себя от мошенников, пожалуйста, остерегайтесь подделок и свяжитесь с правильной кредитной компанией. com или whatsapp + 1-989-394-3740. ,

    ОтветитьУдалить