SYBASE: SQL извикване за намиране на първите налични (островни) ID

Трябва да върна подреден списък с определена дължина на наличните идентификатори на клиента.

например:

Трябва да намеря ПЪРВИТЕ 5 неизползвани идентификатора на клиента между 1500 и 3000

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

Работя със стара версия на SYBASE, която няма команда "TOP". Досега намерих следната заявка, за да ми даде следващия наличен customerID (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
така например ако стойността на customerIDs= 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
Благодаря ви за това. За съжаление това няма да работи за мен, ще ми трябва избран оператор за моята цел (ако е възможно). Надяваме се, че това ще помогне на някой друг в бъдеще все пак :) - 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