Вопрос по SQL

ifani

Что-то я никак сообразить не могу:
Есть некоторое множество чисел, и есть таблица, в одном из столбцов которой могу быть числа из этого множества - собственно, вопрос: можно ли как-то написать запрос, который бы вернул те числа из заданного множества, которые не встречаются в данной таблице (то есть не существует записей с этим числом в столбце)?
База - оракл восьмёрка.

0000

Если задать множество чисел N_1, ..., N_k как

select N_1 a from dual
union
select N_2 a from dual
union
...

То искомый ответ
select a from (ВышеПриведенныйСелект) where a not in (select a from T1)

rosali

ну создай таблицу с этими числами, и сделай потом left join подходящий

Boris1980


select Id
from main_table
MINUS
select Id
from other_table

main_table - твое множество
other_tabele - таблица с данными
Это множество как задано? Да и от количества данных во множестве и таблице зависит как запрос писать, если он регулярный.

ifani

code:
select N_1 a from dual
union
select N_2 a from dual
union
...
Класс, это именно то, что я хотел увидеть :)
Я пробывал делать подзапрос select n1,n2,n3 from dual, но понятное дело, результатом была одна строчка со всем числами. До юниона как-то не догадался. Причём задачу уже решил по-другому, но такое решние запомню :)

ifani

Ну, дополнительная таблица - это довольно очевидное решение :)
Интересовала именно возможность решить такую задачу лишь одним запросом (то есть без предварительного создания чего-либо).
Сам я её как раз примерно так и решил - просто тупо взял первую попавшуюся таблицу, убедился, что в ней есть нужные мне айдишники и сделал подзапрос select id from some_table where id in (n1,n2,n3) :) Так этот запрос мне надо было выполнить всего один раз, то в данном случае этот хак прошёл, но стало интересно, как это сделать в общем случае.

ifani

main_table - твое множество
Вот меня как раз и интересовало, как можно представить моё множество в виде таблицы, чтобы потом можно было делать из неё селект, но при этом физически никаких таблиц не создавать. Выше уже дали ответ :)
Всем большое спасибо :) В который раз убеждаюсь, что программинг - самый лучший раздел :)

Boris1980

Ты точно на верном пути?
Сколько у тебя там элементов и как часто запрос пускать собрался?
но при этом физически никаких таблиц не создавать

ifani

Сколько у тебя там элементов и как часто запрос пускать собрался?
Шесть таких элементов и это был единоразовый апдейт :)

Boris1980

Если по умному, то нужно писать функцию, которая строку с этими элементами переводит в таблицу, что-то типа такого в пакете можно оформить.

create or replace type TId is object(Id number(16
create or replace type TIdSet is table of TId

function Transform(pString varchar2) return TIdSet
is
t TIdSet := TIdSet;
i number;
vString varchar2(2000);
n number;
m number;
begin
vString := pString;

if SubStr(vString, Length(vString 1) <> ',' then
vString := vString || ',';
end if;

i := 1;
n := InStr(vString, ',');
while n <> 0 loop
n := InStr(vString, ',');
m := to_number(SubStr(vString, 1, n - 1;
t.Extend;
t(i) := TId(m);
i := i + 1;
vString := Substr(vString, n + 1, 2000);
end loop;
Return t;
end;

Задачка решится так.

select Id
form table (Transform('1, 2, 3, 4, 5') );

Papazyan

setOfNumbers except exec id from table

Boris1980

Можешь пояснить свою мысль?

Papazyan

Можешь пояснить свою мысль?
Это решение задачи в другой БД, чтобы оракл-девелоперы завидовали.

ifani

Классно, спасибо - не знал, что в курсоры можно писать ручками.
P.S.:
Я правильно понимаю, что тут небольшая очепятка и "type TCursor is ref cursor" должно быть "type TIdSet is ref cursor" ?

Boris1980

Я ступил похоже, сейчас исправил (см. выше).

0000

Что то мне не кажется, что по умному для такого писать функцию надо, к тому же через парсинг строк.
Вот еще вариант, как сгенерить нужный набор чисел (только седня до Oracle добрался правда тока натуральных.
На 8-ке может правда и не работать

select level
from dual
where level in (3, 4, 8, 15, 23)
connect by level < greatest (3, 4, 8, 15, 23)

Boris1980

....
connect by level <= greatest (3, 4, 8, 15, 23)
Знак "равно" пропустил.
А так, да можно разными способами задачку решить. Мое решение, когда множество задано в виде строки с разделителем запятая.

fester


create table table1
as
select level N
from DUAL
connect by level <= 11;

create table mnojestvo
as
select level N
from DUAL
connect by level <= 5;

-- mojet byt polezen dlya bolshikh tablits
select
Q.*
from TABLE1 Q, MNOJESTVO W
where Q.N = W.N(+)
and W.N is null
Оставить комментарий
Имя или ник:
Комментарий: