28 нояб. 2011 г.

Посчитать от 1 до N

Можно с помощью рекурсивного CTE:
with recursive enum as (
  select 1 as n from rdb$database
  union all
  select (e.n + 1) as n from enum e
  where e.n < :MAX_N
  )
select n from enum
Максимальное значение параметра :MAX_N ограничено внутренним лимитом сервера на выполнение рекурсивных запросов (несколько тысяч для FB 2.5).

Приведенный код не настолько бесполезен, как может показаться на первый взгляд. С его помощью можно реализовать поиск свободного идентификатора группы пользователей в таблице GD_USERGROUP:

select
  first 1 e.n
from
  gd_usergroup g right join (
    with recursive enum as (
      select 7 as n from rdb$database
      union all
      select (e.n + 1) as n from enum e
      where e.n < 32
      )
    select
      n
    from
      enum) e on e.n = g.id
where
  g.id is null
order by
  1
Пусть вас не смущает семерка в качестве начального числа счета — первые шесть групп стандартные и не могут быть удалены из таблицы.

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

igor6003 комментирует...

Вот ещё счётчик от a до b без ограничений:

create procedure enum (a integer, b integer)
returns (n integer)
as
begin
n=a;
while (n <= b) do
begin suspend; n = n + 1; end
end

А вывести первый не использованный id можно как-то так:

execute block ( a integer=: a, b integer=: b)
returns ( n integer, id integer)
as
begin
n=a;
while (n <= b) do
begin
id = 0;
select g.id from gd_usergroup g where g.id = :n into :id;
if (id = 0) then begin suspend; leave; end
n = n + 1;
end
end

Andrei комментирует...

Да, можно и так. Но, хотелось обойтись без хранимых процедур и алгоритмической обработки. Т.е. свести все только к SELECT запросу.

Отправить комментарий