Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.10.23;
Скачать: CL | DM;

Вниз

Найти дырки в таблице   Найти похожие ветки 

 
Drakosha ©   (2005-09-06 18:19) [0]

Имеется таблица с уникальным полем, значения в нём должны быть
от 1 до 100.
пример
2
3
4
89
90
Необходимо получить отсутствующие номера (т.е. 1,5,6,...88,91..100)
Можно ли это сделать не привлекая дополнительную таблицу со всеми значениями от 1 до 100?


 
Shopot ©   (2005-09-06 18:42) [1]

Можно!


var
 Numbers: array [1..100] of Byte;
 IsEntry: array [1..100] of Boolean;

procedure InitArrays;
var
 i: Integer;
begin
 for i := 1 to 100 do
 begin
   Numbers [i] := i;
   IsEntry [i] := False;
 end;
end;

procedure LookIntoTable;
var
 i, RecordCount: Integer;
begin
 RecordCount := Table.RecordCount;

 if RecordCount > 100 Exit;

 for i := 0 to RecordCount - 1 do
 begin
   if Table["_ID"] = Numbers [i] then
     IsEntry [i] := True
   else
     IsEntry [i] := False;
 end;
end;


Таким образом знаем какие числа входят и каких нет.
Наример:


 ...
 if IsEntry [10] then
   ShowMessage ("Number = " + IntToStr (Number [10]) + " exists!");
 ...


Кроме того Numbers массив байт, но может быть и строк и записей и т.п.


 
Lexer ©   (2005-09-06 19:57) [2]

Как вариант, - можно написать простенькую процедурку:
create procedure get_dyrki
returns (order_number smallint)
begin
 last_order_number = 0;
 while order_number < 100 do
 begin
   order_number = order_number + 1;
   if (not(exists(select order_number from table_1 where order_number = :order_number))) then suspend;
  end
end


 
Desdechado ©   (2005-09-06 20:26) [3]

ХП написать :)


 
Desdechado ©   (2005-09-06 21:06) [4]

хм, отвлекся, не запостив, и на тебе - опередили


 
Zacho ©   (2005-09-07 08:37) [5]

Да можно и одним запросом:

SELECT T1.ID+1
FROM MY_TABLE T1
LEFT JOIN MY_TABLE T2
 ON T1.ID+1=T2.ID
WHERE T2.ID IS NULL


По крайней мере на IB/FB такой запрос работает, на других СУБД - не знаю :)


 
Val ©   (2005-09-07 10:40) [6]

>[5] Zacho ©   (07.09.05 08:37)
в данном примере, он не покажет номера с 5 по 88, а только 5-й. т.е. он находит "первый пустой" за текущим id.


 
Anatoly Podgoretsky ©   (2005-09-07 11:28) [7]

Почему 5, а не 1


 
Zacho ©   (2005-09-07 11:41) [8]

Val ©   (07.09.05 10:40) [6]

Да, ты прав. Если "дырки" идут подряд, то такой запрос покажет только первую в диапазоне.
Сожалею, был не внимателен.
Так что для нахождения всех дырок мой запрос не подходит. А вот для нахождения первой или последней - вполне, правда автору вопроса нужно не это :)

2 Drakosha ©  : укажи СУБД, возможно что для твоей СУБД существует решение именно одним запросом.


 
Val ©   (2005-09-07 11:55) [9]

>[7] Anatoly Podgoretsky ©   (07.09.05 11:28)
я про промежуток с "дырками" более одной.


 
Sergey13 ©   (2005-09-07 12:02) [10]

Вариант для Оракла
select rownum from all_objects where rownum<101
minus
select uniq_Field from My_Table

Вместо all_objects можно использовать любую таблицу/вьюху с гарантировано бОльшим 100 количеством записей.


 
Val ©   (2005-09-07 12:08) [11]

>Sergey13 ©   (07.09.05 12:02)
Интересное решение. Думаю, можно применить к любому серверу, заменив минус на not in/not exists и константу на select max. Дело за нужной таблицей.


 
Desdechado ©   (2005-09-07 12:10) [12]

Sergey13 ©   (07.09.05 12:02) [10]
элегантно, но не удовлетворяет условию "не привлекая другую таблицу со всеми 1..100"


 
Val ©   (2005-09-07 12:14) [13]

мда. в [11] я прогнал. rownuma-то не найти в других серверах :( сорри.


 
Sergey13 ©   (2005-09-07 12:15) [14]

2[12] Desdechado ©   (07.09.05 12:10)
Я так думаю ограничение касалось специально созданой таблицы.
Хотя - автору, которого не видно, виднее. 8-)


 
Drakosha ©   (2005-09-07 12:26) [15]

Вопрос задавал вечером и только сейчас глянул ответы.
Что ж начнём по порядку:

2Shopot ©
2Lexer ©  
Имелось ввиду не использование никаких языков программирования или хранимых процедур.


 
Drakosha ©   (2005-09-07 12:27) [16]


> Zacho ©   (07.09.05 11:41) [8]

Извиняюся ... показалося что ставил птичку на оракле


 
Drakosha ©   (2005-09-07 12:28) [17]


> Sergey13 ©   (07.09.05 12:02) [10]

Вроде то что надо!!! сейчас опробую


 
Drakosha ©   (2005-09-07 12:33) [18]


> Sergey13 ©   (07.09.05 12:02) [10]


Во!! То что надо! Огромное спасибо!


 
Lexer ©   (2005-09-07 12:34) [19]

Без таблиц, без процедур :)
SELECT 1
 FROM EMPLOYEE WHERE NOT EXISTS (SELECT id_employee FROM EMPLOYEE WHERE id_employee = 1)
UNION
SELECT 2
 FROM EMPLOYEE WHERE NOT EXISTS (SELECT id_employee FROM EMPLOYEE WHERE id_employee = 2)
UNION
SELECT 3
 FROM EMPLOYEE WHERE NOT EXISTS (SELECT id_employee FROM EMPLOYEE WHERE id_employee = 3)
UNION
SELECT 4
 FROM EMPLOYEE WHERE NOT EXISTS (SELECT id_employee FROM EMPLOYEE WHERE id_employee = 4)
UNION
SELECT 5
 FROM EMPLOYEE WHERE NOT EXISTS (SELECT id_employee FROM EMPLOYEE WHERE id_employee = 5)
UNION
SELECT 6
 FROM EMPLOYEE WHERE NOT EXISTS (SELECT id_employee FROM EMPLOYEE WHERE id_employee = 6)
UNION
.....
.....
SELECT 100
 FROM EMPLOYEE WHERE NOT EXISTS (SELECT id_employee FROM EMPLOYEE WHERE id_employee = 100)


 
Drakosha ©   (2005-09-07 12:41) [20]


> Lexer ©   (07.09.05 12:34) [19]
>
> Без таблиц, без процедур :)


:)
ню-ню
без таблиц имелось ввиду что я не создаю лишних или временных а юзаю какие нить уже существующие....
зы от 1 до 100 это я написал для примера...на самом деле там речь о четырёх разрядных значениях...вот я б попарился с твоим вариантом :)


 
Val ©   (2005-09-07 13:16) [21]

>[20] Drakosha ©   (07.09.05 12:41)
Не факт что в all_objects будет нужное вам количество строк. А выставлять для себя ограничение "без процедур, без таблиц", без видимых на то причин, является глупостью по-моему. Что называется - "Хотите гемора - нате!".


 
SvetaK   (2005-09-07 14:06) [22]

Для 3-ёх разрядных значений можно так попробовать...

select nn.nn from (
select  (n2.num*10+n1.num)+1 as nn from
(select 0 as num union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) n1,
(select 0 as num union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) n2
) nn
left join (SELECT * FROM MY_TABLE) t2 on nn.nn=t2.id
where t2.id is null order by 1

,а для четырёх разрядных нужно еще полторы строки напарить - успехов!


 
SvetaK   (2005-09-07 14:23) [23]

В предпоследней строчке уточняю: вместо * надо  id
left join (SELECT id FROM MY_TABLE) t2 on nn.nn=t2.id


 
Drakosha ©   (2005-09-07 14:45) [24]


> >[20] Drakosha ©   (07.09.05 12:41)
> Не факт что в all_objects будет нужное вам количество строк.
> А выставлять для себя ограничение "без процедур, без таблиц",
> без видимых на то причин, является глупостью по-моему. Что
> называется - "Хотите гемора - нате!".

В нашем проекте в all_objects находится свыше 30 000 записей тобишь    всё нармуль.

Всем спасибо за участие и помощь.


 
Val ©   (2005-09-07 14:51) [25]

...понадобились "дырки" с 30 003 по 30 010... :)
кстати, на этот обзор нужны права дба, как я понимаю.


 
Sergey13 ©   (2005-09-07 14:54) [26]

2[25] Val ©   (07.09.05 14:51)
>кстати, на этот обзор нужны права дба, как я понимаю.
Нет. Но для ДБА записей гораздо больше чем для простого узера. 8-)


 
Val ©   (2005-09-07 15:02) [27]

ок. но тогда простой юзер вообще получит пустую выборку, так как он не owner ни одного объекта?


 
Sergey13 ©   (2005-09-07 15:15) [28]

2[27] Val ©   (07.09.05 15:02)
Наверное. Лень проверять.



Страницы: 1 вся ветка

Текущий архив: 2005.10.23;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.041 c
9-1118343860
Ksander
2005-06-09 23:04
2005.10.23
игра


1-1128024783
lesee
2005-09-30 00:13
2005.10.23
Отбросить тень TLabel и получит её регион и регин


11-1109452786
Ripper
2005-02-27 00:19
2005.10.23
REG MULTI STRING


14-1128183159
syte_ser78
2005-10-01 20:12
2005.10.23
12 дней не курю!


1-1128075034
Николай1
2005-09-30 14:10
2005.10.23
MDIChild и TreeView не возвращается фокус