Найти следующий неиспользуемый идентификатор в таблице SQL, которая имеет непрерывные диапазоны

У меня есть две таблицы, подобные следующим:

TABLE1:
=======
somid, tobeupdated
1    ,  null
2    ,  null
3    ,  null
10   ,  null

TABLE2:
=======
rangeofids
2
3
9
10
11
12
13

Я должен обновить TABLE1.tobeupdated (или обнаружил, что его 'должно быть значением) на основе следующих критериев:

  1. если TABLE1.somid NOT exists in TABLE2.rangeofids, то ожидаемый результат: tobeupdated = TABLE1.somid
  2. еще найти следующий доступный (или неиспользованный) TABLE2.rangeofids что больше, чем TABLE1.somid

Итак, ожидаемые значения: bu

TABLE1:
=======
somid, tobeupdated
1    ,  1
2    ,  4
3    ,  4
10   ,  14

Я очень старался, но самое простое решение, которое я нашел, - это создание временной таблицы с полной последовательностью идентификаторов (из 1 в max(rangeofids)+1) MINUS TABLE2.rangeofids так что я могу найти MIN(TMPTABLE.id) where TMPTABLE.ID > TABLE1.somid,

Но разве нет лучшего решения (без временной таблицы)?

Примечание: я не могу создавать процедуры / функции и т. Д., Поэтому это должен быть стандартный (Oracle 10) SQL.

1 ответ

Решение

Это моя попытка.

Сначала мы должны решить, используя только table2, какое значение должно возвращаться после нахождения значения там.

select rangeofids, 
  candidate, 
  nvl(candidate,lead(candidate ignore nulls) over (order by rangeofids)) as full_candidate
from (
    select rangeofids, case when dist=1 then null else rangeofids+1 end as candidate
    from (
        select rangeofids,
               lead(rangeofids) over (order by rangeofids) - rangeofids as dist
        from table2
        )
      );

После этого merge into table1 with Выбор ниже решит проблему:

select someid, nvl(full_candidate, someid) 
from table1 a
left join (    
    --the above query
) b
on a.someid = b.rangeofids;

Смотрите SQLFIDDLE.

Другие вопросы по тегам