Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2003.10.16;
Скачать: [xml.tar.bz2];

Вниз

Тут пролетал запрос, возвращающий   Найти похожие ветки 

 
dtm   (2003-09-23 17:51) [0]

Уважаемые, напомните, плз. Вроде как его тут публиковал уважаемый Johnmen, но на тот момент я его скопировать не смог. Буду благодарен, если опубликуете его снова.


 
kaif   (2003-09-23 17:54) [1]

Дырки это как? Поясни.


 
Vlad   (2003-09-23 17:54) [2]

Странно... поиск по слову "дырки" ничего не дал :)


 
dtm   (2003-09-23 18:02) [3]

Кхм... Шутнички ;)

Генерятся уникальные номера записей. Потом некоторые из них удаляются. Необходимо, чтобы генератор не просто выдавал следующее значение, а выбирал минимальное из не использованных. Требуется это не для ключевого поля, а просто по условию постановки задачи - каждая операция (именно о них речь) должна иметь уникальный номер (не ключевое поле), причём "дырки" в нумерации недопускаются.


 
Johnmen   (2003-09-23 18:03) [4]

==================================================================
SELECT T.ID+1, MIN(T1.ID)-1, MIN(T1.ID)-T.ID-1
FROM TABLE1 T
JOIN TABLE1 T1 ON T.ID<T1.ID
WHERE T.ID<=1000 AND T1.ID<=1000
GROUP BY T.ID
HAVING MIN(T1.ID)-T.ID>1
>Получаем промежутки в которых удалены записи.
>В первой колонке будет начальный ID промежутка, во второй - >конечный.
>В третьей количество удаленных записей в промежутке.
==================================================================


 
kaif   (2003-09-23 18:05) [5]

А удалять операции задним числом допускается?


 
kaif   (2003-09-23 18:09) [6]

2 Johnmen © (23.09.03 18:03) [4]
Очень хитрый запрос... Я пока не врубился. Но на декартово произведение сильно смахивает. А для ID < 100000 заработает? Или лучше не пробовать?


 
Val   (2003-09-23 18:17) [7]

#8O ну и запросик. А без join, так, можно?
SELECT T.ID+1, MIN(T1.ID)-1, MIN(T1.ID)-T.ID-1
FROM TABLE1 T, TABLE1 T1
WHERE T.ID<=1000 AND T1.ID<=1000 and
T.ID<T1.ID
GROUP BY T.ID
HAVING MIN(T1.ID)-T.ID>1


 
NickBat   (2003-09-23 18:21) [8]

Хороший запрос. Только сдается мне будет очень медленный. Я такую проблему решал занесением всех удаленных уникальных номеров в отдельную табличку, а потом из нее можно автоматом вытянуть номер, можно пользователю предложить. Все прозрачней и надежней.


 
Johnmen   (2003-09-23 18:22) [9]

>kaif © (23.09.03 18:09)

Не совсем декартово :), т.к. есть условие соединения.
Для ID < 100000 заработает. Это просто верхняя планка значений ID. Можно выкинуть это WHERE.
Попробовать обязательно стоит ! :)


 
Johnmen   (2003-09-23 18:27) [10]

>Val © (23.09.03 18:17)

Конечно :)

>NickBat © (23.09.03 18:21)

Зависит от количества записей, естественно.


 
Val   (2003-09-23 18:30) [11]

>Johnmen © (23.09.03 18:27) [10]
пугает, знаете-ли :)


 
dtm   (2003-09-23 18:38) [12]

2 NickBat

Не могу, если я пользователю буду ещё вываливать диалог выбора удалённого кем-то номера, это обязательно вгонит его в долговременный ступор с глубоким залипанием =(. Со всеми вытекающими для меня как разработчика.

Что достаточно долго - это не страшно. Работать программа должна в сети из трёх-четырёх машин, не думаю, что будет слишком заметно.

Кстати, а создание индекса для этого запроса поможет или нет? И можно ли его бескровно вставить в процедуру генерации уникального номера? Думаю, что можно, но хотелось бы ещё и подтверждение услышать ;)


 
MsGuns   (2003-09-23 18:39) [13]

Адын мааалэнкый мынус - пропускает, сабака, ведущую дырку.
Савсэм &8*


 
kaif   (2003-09-23 18:39) [14]

2 Johnmen © (23.09.03 18:22) [9]
:))))

вообще-то я бы наверно на IB хранимую процедуру написал вместо такого запроса...

что-нибудь вроде:

CREATE PROCEDURE ALL_HOLES_IN_T1
RETURNS(
HOLE_START INTEGER,
HOLE_END INTEGETR,
HOLE_WIDTH INTEGER)
AS
DECLARE VARIABLE ID INTEGER;
DECLARE VARIABLE LAST_ID INTEGER;
BEGIN
FOR SELECT ID FROM T1 ORDER BY ID
INTO :ID DO
BEGIN
IF ID - LAST_ID > 1 THEN
BEGIN
HOLE_START = LAST_ID + 1;
HOLE_END = ID - 1;
HOLE_WIDTH = ID - LAST_ID - 1;
SUSPEND;
END
LAST_ID = ID;
END
END

Тогда тормоз будет зависеть линейно от числа записей, а не квадратично.


 
kaif   (2003-09-23 18:41) [15]

Пардон, скобки как всегда забыл:
IF (ID - LAST_ID > 1) THEN


 
Sandman25   (2003-09-23 18:53) [16]

[4] Johnmen © (23.09.03 18:03)

Это похоже на вот это?

select t1.id + 1, t2.id - 1
from t1, t t2
where t2.id = (select min(id) from t where id > t1.id)
and t1.id <> t2.id - 1


 
Sandman25   (2003-09-23 18:54) [17]

select t1.id + 1, t2.id - 1
from t t1, t t2
where t2.id = (select min(id) from t where id > t1.id)
and t1.id <> t2.id - 1


 
NickBat   (2003-09-23 18:57) [18]

> если я пользователю буду ещё вываливать диалог выбора удалённого кем-то

Зачем диалог?

Есть таблица с удаленными номерами Т1, из нее выбираешь наименьший и вставляешь в основную таблицу Т, из Т1 удаляешь.


 
MsGuns   (2003-09-23 19:02) [19]

>kaif © (23.09.03 18:39) [14]
Фуй, как скучно ! Никакой фантазии
То ли дело Johnmen ;)))


 
dtm   (2003-09-23 19:09) [20]

[18] NickBat

Как один из вариантов покатит. Вполне, я думаю.


 
Zacho   (2003-09-23 19:11) [21]

Ну, и свой вариант такого запроса приведу :
SELECT MIN(T.ID)+1
FROM MY_TABLE T
LEFT JOIN MY_TABLE T1
ON T.ID+1=T1.ID
WHERE T1.ID IS NULL
Возвращает первое "свободное" ID.


 
MsGuns   (2003-09-23 19:12) [22]

select t1.iid + 1, t2.iid - 1
from INV t1, INV t2
where t2.iid = (select min(iid) from INV where iid > t1.iid)
and t1.iid <> t2.iid - 1
union
select 1, t3.iid-1
from INV t3
where t3.iid=(select min(iid) from INV) and (t3.iid>1)

А вот так возвращает даже ведущую дырочку.


 
kaif   (2003-09-23 19:12) [23]

2 MsGuns © (23.09.03 19:02) [19]
Согласен. Johnmen - профи.
Но я подхожу к программированию как к ремеслу по удовлетворению юзера, а не как к искусству для искусства. Хотя, может, это и неправильно...
Аргумент в пользу запроса Johnmen - переносимость на любой сервер.
Хотя как именно дырки будут устраняться, мне пока непонятно. Лично мне если бы юзеры такую задачу поставили (нумеровать операции с возможностью удалять старые и заполнять дырки), я бы просто вообще убил поле нумерации операций и нумеровал бы их при печати или выводе на экран.


 
Sandman25   (2003-09-24 10:05) [24]

[22] MsGuns © (23.09.03 19:12)
Точно! А я и забыл про первую дырку.

[23] kaif © (23.09.03 19:12)
>переносимость на любой сервер.
Нет. На Informix не работает.


 
Val   (2003-09-24 10:48) [25]

Sandman25 © (24.09.03 10:05) [24]
Нет. На Informix не работает.
Почему? Если заменить join на доп. условие тоже не работает?


 
Sandman25   (2003-09-24 11:02) [26]

[25] Val © (24.09.03 10:48)
>Почему? Если заменить join на доп. условие тоже не работает?

Тогда работает.


 
Sandman25   (2003-09-24 11:11) [27]

Я тут протестировал скорость запросов в таблице c 165 тыс. записей. Запрос
select t1.id + 1, t2.id - 1
from t t1, t t2
where t2.id = (select min(id) from t where id > t1.id)
and t1.id <> t2.id - 1
выполнился за 55 секунд, запрос
SELECT T.ID+1, MIN(T1.ID)-1, MIN(T1.ID)-T.ID-1
FROM TABLE1 T
JOIN TABLE1 T1 ON T.ID<T1.ID
WHERE T.ID<=1000 AND T1.ID<=1000
GROUP BY T.ID
HAVING MIN(T1.ID)-T.ID>1
выполнялся более 3 минут, и я его прервал.
Я думаю, замедление связано с использованием GROUP BY и HAVING.

PS. По id есть индекс, первый запрос я выполнял раньше второго, поэтому выигрыш за счет кэширования исключен.


 
Sandman25   (2003-09-24 11:13) [28]

Забыл написать, что я убрал ограничение на ID, поэтому во втором случае запрос был
SELECT T.ID+1, MIN(T1.ID)-1, MIN(T1.ID)-T.ID-1
FROM TABLE1 T, TABLE1 T1
WHERE T.ID<T1.ID
GROUP BY T.ID
HAVING MIN(T1.ID)-T.ID>1


 
Danilka   (2003-09-24 11:25) [29]

Как говорил мне тесть "дыры, дырки и дырочки они у женщин, а это - отверстия".


 
Val   (2003-09-24 11:40) [30]

>Danilka © (24.09.03 11:25) [29]
:) на самом деле это - интервалы


 
Johnmen   (2003-09-24 11:43) [31]

Согласен с kaif ©, что рассматриваемый вопрос лежит не в плоскости практического применения, а с скорее в теоретической, не привязанной к реальным построениям систем.
А по поводу начальной дырки, так нет такого понятия. Поясню.
Есть интервал с дырками. Конечное значение интервала - максимальное значение ID. А вот минимальное почему же 0, или 1 ??? Вовсе нет. Минимальное - минимум ID. И никак иначе. В противном случае придем к нарушению понятия "дырки в интервале". По определению интервал не может начинаться с дырки.
Конечно можно считать минимумом 0 или 1. Но это уже искусственный частный случай.
И, конечно же, самое быстрое здесь это ХП.

(Не может быть, что я столько слов тут написал :))

>Sandman25 © (24.09.03 11:11)

Хороший запрос. И по идее, действительно, должен работать бастрее.
Посмотрел планы и того и другого. В общем, понятно, почему быстрее.


 
Alex_Raider   (2003-09-24 12:10) [32]

У тебя сама постановка алгоритмики и способа решения неправильная.

Следует сделать иначе - ничего не удалять,
а просто помечать записи(документы) как "удалено, недоступно, заблокировано".

И никаких "дырок" бы не появилось.
Вот так-то.


 
Sandman25   (2003-09-24 12:31) [33]

>Следует сделать иначе - ничего не удалять,
а просто помечать записи(документы) как "удалено, недоступно, заблокировано".

Расходуется лишняя память, замедляется поиск и вставка записей.


 
Alex_Raider   (2003-09-24 12:48) [34]

Каждому свое.
Извращайся до посинения,
если неспособен оценить трудоемкость/затраты решений.

А если хочешь экономить память и дисковое пространство - не используй версионники, C/S, и Windows вместе с Delphi.
Используй Zx Spectrum 48, все 49152 байта RAM твои...


 
MsGuns   (2003-09-24 12:53) [35]

>Johnmen © (24.09.03 11:43) [31]
Ты же сам говоришь, что это вопрос скорее теоретический и тут же принимаешься критиковать "начальную" дырку с чисто практической т.зр.
;))
Если же иметь в виду "вакантность" UID, то не вижу никакой разницы, откуда его выбирать, т.е. будет это 1 или 1001 - нет для физической модели БД никакой разницы Другими словами, мне больше по душе итоговая последовательность

1,2,3,56,57,58,59,101,102

нежели

56,57,58,59,60,61,62,101,102

Чисто эстетически.


 
Sandman25   (2003-09-24 12:55) [36]

[34] Alex_Raider © (24.09.03 12:48)

Вы принципиальный сторонник отказа от оптимизации? Если клиента что-то не устраивает, пуст покупает четвертый винт и пятый процессор?


 
Johnmen   (2003-09-24 13:14) [37]

>MsGuns © (24.09.03 12:53)

Нет-нет-нет. Именно с теоретической. По-моему, "начальная дырка" это скорее всего "ближе к практике", если вообще тут можно о практике говорить... =o)


 
Alex_Raider   (2003-09-24 16:01) [38]

>>Вы принципиальный сторонник отказа от оптимизации? Если >>клиента что-то не устраивает, пуст покупает четвертый винт и >>пятый процессор?

Нет, я сторонник здравого смысла.
:-)


 
Sandman25   (2003-09-24 16:12) [39]

:)


 
dtm   (2003-09-24 18:28) [40]

Alex_Raider [32]
> У тебя сама постановка алгоритмики и способа решения неправильная.
>Следует сделать иначе - ничего не удалять,
а просто помечать записи(документы) как "удалено, недоступно, заблокировано".

;) Всё у меня правильно.
Пользователь вызывают новую операцию, она должна уже на этапе создания иметь уникальный номер - она его и имеет, получая от генератор. Если пользователь отменил во время оформления операцию - номер теряется, так как уже был сгенерирован. Естественно, что в базе ничего не остаётся, так что помечать "удалено, недоступно, заблокировано" просто нечего.
А есть ещё софтина, обрабатывающая информацию об операциях, поступающих из разных концов Беларуси, и по правилам ведения работы заказчика (а они определяются международной конвенцией) номера у документов должны быть по возможности последовательные, то есть без "дырок". Может, "дырки" всё равно будут, но для сертификации программы перед использованием я обязан вложить подобную функцию в программу. Иначе никак.
Так что не надо говорить, что кто-то поставил задачу неправильно...



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

Форум: "Базы";
Текущий архив: 2003.10.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.018 c
9-51048
Арм
2003-04-15 03:57
2003.10.16
Беда с текстурами в OpeGL


6-51382
Vinter
2003-08-19 14:59
2003.10.16
MS Outlook


14-51476
Yorick
2003-09-24 13:23
2003.10.16
Как можно отвоевать девушку?


8-51360
Olim
2003-06-16 16:55
2003.10.16
Как записать звук из микрафона


3-51105
RomDron
2003-09-24 16:56
2003.10.16
DbGreed... Как сохранить данные?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский