![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Тут пролетал запрос, возвращающий
dtm © (2003-09-23 17:51:00)
Уважаемые, напомните, плз. Вроде как его тут публиковал уважаемый Johnmen, но на тот момент я его скопировать не смог. Буду благодарен, если опубликуете его снова.
Sandman25 (2003-09-24 11:13:00) [21]
Забыл написать, что я убрал ограничение на 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
Sandman25 (2003-09-24 11:11:00) [22]
Я тут протестировал скорость запросов в таблице c 165 тыс. записей. Запрос
select t1.id + 1, t2.id - 1выполнился за 55 секунд, запрос
from t t1, t t2
where t2.id = (select min(id) from t where id > t1.id)
and t1.id <> t2.id - 1
SELECT T.ID+1, MIN(T1.ID)-1, MIN(T1.ID)-T.ID-1выполнялся более 3 минут, и я его прервал.
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
Я думаю, замедление связано с использованием GROUP BY и HAVING.
PS. По id есть индекс, первый запрос я выполнял раньше второго, поэтому выигрыш за счет кэширования исключен.
Sandman25 (2003-09-24 11:02:00) [23]
[25] Val © (24.09.03 10:48)
>Почему? Если заменить join на доп. условие тоже не работает?
Тогда работает.
Val (2003-09-24 10:48:00) [24]
Sandman25 © (24.09.03 10:05) [24]
Нет. На Informix не работает.
Почему? Если заменить join на доп. условие тоже не работает?
Sandman25 (2003-09-24 10:05:00) [25]
[22] MsGuns © (23.09.03 19:12)
Точно! А я и забыл про первую дырку.
[23] kaif © (23.09.03 19:12)
>переносимость на любой сервер.
Нет. На Informix не работает.
kaif (2003-09-23 19:12:00) [26]
2 MsGuns © (23.09.03 19:02) [19]
Согласен. Johnmen - профи.
Но я подхожу к программированию как к ремеслу по удовлетворению юзера, а не как к искусству для искусства. Хотя, может, это и неправильно...
Аргумент в пользу запроса Johnmen - переносимость на любой сервер.
Хотя как именно дырки будут устраняться, мне пока непонятно. Лично мне если бы юзеры такую задачу поставили (нумеровать операции с возможностью удалять старые и заполнять дырки), я бы просто вообще убил поле нумерации операций и нумеровал бы их при печати или выводе на экран.
MsGuns (2003-09-23 19:12:00) [27]
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)
А вот так возвращает даже ведущую дырочку.
Zacho (2003-09-23 19:11:00) [28]
Ну, и свой вариант такого запроса приведу :
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.
dtm (2003-09-23 19:09:00) [29]
[18] NickBat
Как один из вариантов покатит. Вполне, я думаю.
MsGuns (2003-09-23 19:02:00) [30]
>kaif © (23.09.03 18:39) [14]
Фуй, как скучно ! Никакой фантазии
То ли дело Johnmen ;)))
NickBat (2003-09-23 18:57:00) [31]
> если я пользователю буду ещё вываливать диалог выбора удалённого кем-то
Зачем диалог?
Есть таблица с удаленными номерами Т1, из нее выбираешь наименьший и вставляешь в основную таблицу Т, из Т1 удаляешь.
Sandman25 (2003-09-23 18:54:00) [32]
select t1.id + 1, t2.id - 1
from tt1, 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:53:00) [33]
[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
kaif (2003-09-23 18:41:00) [34]
Пардон, скобки как всегда забыл:
IF (ID - LAST_ID > 1) THEN
MsGuns (2003-09-23 18:39:00) [35]Адын мааалэнкый мынус - пропускает, сабака, ведущую дырку.
Савсэм &8*
kaif (2003-09-23 18:39:00) [36]
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
Тогда тормоз будет зависеть линейно от числа записей, а не квадратично.
dtm (2003-09-23 18:38:00) [37]
2 NickBat
Не могу, если я пользователю буду ещё вываливать диалог выбора удалённого кем-то номера, это обязательно вгонит его в долговременный ступор с глубоким залипанием =(. Со всеми вытекающими для меня как разработчика.
Что достаточно долго - это не страшно. Работать программа должна в сети из трёх-четырёх машин, не думаю, что будет слишком заметно.
Кстати, а создание индекса для этого запроса поможет или нет? И можно ли его бескровно вставить в процедуру генерации уникального номера? Думаю, что можно, но хотелось бы ещё и подтверждение услышать ;)
Val (2003-09-23 18:30:00) [38]
>Johnmen © (23.09.03 18:27) [10]
пугает, знаете-ли :)
Johnmen (2003-09-23 18:27:00) [39]
>Val © (23.09.03 18:17)
Конечно :)
>NickBat © (23.09.03 18:21)
Зависит от количества записей, естественно.
Johnmen (2003-09-23 18:22:00) [40]
>kaif © (23.09.03 18:09)
Не совсем декартово :), т.к. есть условие соединения.
Для ID < 100000 заработает. Это просто верхняя планка значений ID. Можно выкинуть это WHERE.
Попробовать обязательно стоит ! :)