SYBASE: вызов SQL для поиска первого доступного (островного) идентификатора

Мне нужно вернуть упорядоченный список определенной длины доступных идентификаторов клиентов.

например:

Мне нужно найти ПЕРВЫЕ 5 неиспользуемых идентификаторов клиентов между 1500 и 3000

Table= customer
Column= customerIDs
customerIDs value's= 1500,1502,1503,1507,1508
Return desired= 1501,1504,1505,1506,1509

Я использую старую версию SYBASE, в которой нет команды «TOP». До сих пор я нашел следующий запрос, чтобы дать мне следующий доступный идентификатор клиента (1501), но не знаю, как его изменить, чтобы он возвращал первые 5 результатов, а не только 1.

set rowcount 5 
SELECT  MIN(c.customerIDs )+1 AS NextID 
FROM customer c 
WHERE NOT EXISTS 
  (SELECT NULL 
    FROM customer cu 
    WHERE cu.customerIDs =c.customerIDs +1 
    AND cu.customerIDs >1500)
  AND c.customerIDs <3000

person JavaBeast    schedule 11.02.2015    source источник
comment
Я не понимаю, как вы могли бы сделать это, кроме как написать хранимую процедуру и перебрать значения от 1500 до 3000 или поочередно заполнить таблицу этими значениями и получить несоответствующие через WHERE NOT EXISTS   -  person David Faber    schedule 11.02.2015


Ответы (3)


Хорошо, если вы используете set rowcount 5, это ограничит запрос, чтобы вернуть 5 результатов.

Однако вы используете MIN, который наверняка вернет только 1 запись. Я думаю, ты хочешь использовать

set rowcount 5 
SELECT  c.customerIDs +1 AS NextID 
FROM customer c 
WHERE (c.customerIDs + 1 BETWEEN 1500 and 3000)
  AND c.customerIDs + 1 NOT IN (SELECT c2.customerIDs
                   FROM customer c2)
ORDER BY c.customerIDs 
person Jean-François Savard    schedule 11.02.2015
comment
хорошо, так что это ближе .... но это только возвращает первый идентификатор для каждого пробела в идентификаторах ... это может работать в приведенном выше примере, но когда есть пробел, скажем, 5 идентификаторов, он захватит первый и двинется дальше к первому идентификатору следующего пробела и т. д. - person JavaBeast; 11.02.2015
comment
так, например, если значение идентификатора клиента = 1500,1501,1502,1510,1511,1525,1526, оно возвращает только = 1503, 1512, 1527. - person JavaBeast; 11.02.2015
comment
@JavaBeast Понятно, попробуй новый. Также просьба удалить предыдущий комментарий, так как модератор не любит расширенное обсуждение в комментариях. - person Jean-François Savard; 11.02.2015
comment
Новый запрос дал точно такой же результат. - person JavaBeast; 11.02.2015
comment
Я также обновил вопрос для сценария, который нарушает этот ответ. Спасибо. - person JavaBeast; 11.02.2015
comment
@JavaBeast Мне нужно идти на работу, я попробую что-нибудь другое позже, если никто не решил вашу проблему ... Возможно, вы захотите проверить, используя CONNECT BY для имитации цикла ... - person Jean-François Savard; 11.02.2015

Вот рабочий пример, расширяющий комментарий David Faber:

-- Create a temp table with all possible IDs
declare @min int, @max int
select @min = 1500, @max = 3000

create table #all_ids (id int)
insert #all_ids select @min

-- Keep doubling the number of rows until the limit is reached
while (select max(id) from #all_ids) < @max
begin
    insert #all_ids
    select id + (select count(*) from #all_ids)
    from #all_ids
    where id + (select count(*) from #all_ids) <= @max
end

-- Now find the 5 missing IDs by joining to the customer table on customerIDs, and only returning rows
-- where there is no match, i.e. customerIDs is null
set rowcount 5
select tmp.id
from #all_ids tmp
left join customer c
    on tmp.id = c.customerIDs
where c.customerIDs is null
order by tmp.id
set rowcount 0
person TobyLL    schedule 12.02.2015
comment
Спасибо тебе за это. К сожалению, это не сработает для меня, мне понадобится оператор select для моей цели (если возможно). Надеюсь, это поможет кому-то еще в будущем, хотя :) - person JavaBeast; 12.02.2015
comment
Бит, который возвращает данные, является оператором выбора - я думаю, вы имеете в виду, что вам нужен ТОЛЬКО оператор выбора. Я не думаю, что это возможно. - person TobyLL; 13.02.2015

Один из способов сделать это — сгенерировать последовательность «на лету» из таблицы master..spt_values, которая обычно доступна на большинстве серверов. Эта таблица содержит естественную последовательность, которую можно соединить с самой собой для создания еще большей последовательности. Пример:

create table #customer (customerID int)
go
insert #customer (customerID) values (1500)
insert #customer (customerID) values (1502)
insert #customer (customerID) values (1503)
insert #customer (customerID) values (1507)
insert #customer (customerID) values (1508)
go
set rowcount 5
select customerID
from (
  -- Generate a sequence of 1500-3000
  select 1500 + p2.number * 1000 + p1.number as customerID
  from 
    master..spt_values p1
  , master..spt_values p2
  where 
      p1.type = 'P'
  and p2.type = 'P'
  and p1.number between 0 and 999
  and p2.number between 0 and 1
  and p2.number * 1000 + p1.number <= 1500) seq
where customerID not in (select customerID from #customer)
order by 1
set rowcount 0
go

Возвращает:

 customerID    
 ------------- 
 1501          
 1504          
 1505          
 1506          
 1509          
person Erwin Anema    schedule 03.04.2016