[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Уникальное значение в БД без пропусков
olegod
Здравствуйте, есть база данных, в ней таблица и определённое числовое значение в ней. Числовое значение должно быть уникально(это не совсем id), нужно чтобы при записи нового значения php скрипт находил в базе данных пропущенное числовое значение(база иногда очищается) и делал новую запись с пропущенным числовым значением. Подскажите, возможно ли такое реализовать и как? Заранее огромное спасибо!



Спустя 12 минут, 45 секунд (31.08.2012 - 18:20) Игорь_Vasinsky написал(а):
это довольно сложный алгоритм, во первых нельзя использовать auto_increment, если тока для идентификации не использоать доп поле, а это абсурт т.к. есть автоинкремент, и нужно делать выборку всей таблицы от начала до конца и исекать разницу между следующими друг за другами идентификаторами, которые отличаются на больше чем +1, т.е. следующий должен быть равен - предидущий + 1

Спустя 7 минут, 47 секунд (31.08.2012 - 18:27) olegod написал(а):
На этом значении и нет auto_increment, проходить всю таблицу единственный вариант? mysql ничего на этот случай не предусматривает?

Спустя 5 минут, 9 секунд (31.08.2012 - 18:33) Игорь_Vasinsky написал(а):
ну выборка это не самый страшный момент в этом деле, у парней есть БД с полтора лимона записей и сложными запросами, тут будет работать алгоритм на php

как вариант - писать в отдельную таблицу все удалённые id, с сортировкой по возрастанию

потом провсто делать запрос, брать первый удалённый id из этой таблицы и создавать с ним запись в действующей, после успешного создания очищать.

вообщем это наверно и есть самый оптимальный вариант

Спустя 1 час, 2 минуты, 46 секунд (31.08.2012 - 19:35) olegod написал(а):
Хм... А как бы выглядел оптимальный проход всей таблицы с поиском пропущенного значения?

Спустя 3 минуты, 27 секунд (31.08.2012 - 19:39) Игорь_Vasinsky написал(а):
ты не понял. обходить таблицу для поиска пропущенного id - не надо.

будет доп таблица - в которую заносятся все id при удалении

вот её и нужно проверять - и выбирать первое свободное
если эта таблица пуста - тогда делать запрос в действующую с LIMIT = 1 ORDER BY `id` DESC - отсюда ты получишь последний id - а значит след. id = id+1
но тока если доп таблица пуста.


я не знаю как ещё расжевать.

Спустя 28 минут (31.08.2012 - 20:07) olegod написал(а):
Я Вас понял, просто такой подход не подходит... Дело в том что это значение иногда вводится вручную, т.е. последнее было 1890, а введённое 8000 - тогда огромное кол-во значений между ними будет пропущено, видимо проход всей таблицы - единственный способ

Спустя 15 минут (31.08.2012 - 20:22) Игорь_Vasinsky написал(а):
это не правильный подход. значит нужен идентификатор автоинкремент и ориентироваться на него.

Спустя 3 минуты, 16 секунд (31.08.2012 - 20:25) olegod написал(а):
Такой есть, есть отдельный столбец с id, где нормальный автоинкремент... Только что это даёт, я Вас не совсем понял

Спустя 8 минут, 9 секунд (31.08.2012 - 20:33) Игорь_Vasinsky написал(а):
значит
Цитата
и нужно делать выборку всей таблицы от начала до конца и исекать разницу между следующими друг за другами идентификаторами, которые отличаются на больше чем +1

но это через ж...

у меня есть фраза:

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

Спустя 9 минут, 3 секунды (31.08.2012 - 20:42) olegod написал(а):
Ну а решений нет других... Вот даже в одной ПУ игровыми серверами нашёл такую функцию:
	private function bestPort($server){
$query = mysql_query("SELECT `port` FROM `games` WHERE `server`=".$server." ORDER BY `port`");
$last = 27019;
while($one = mysql_fetch_assoc($query)){
if(($one["port"] - $last) > 1)break;
elseif($one["port"] > $last) $last = $one["port"];
}
return $last + 1;
}

И ничего, работает)

Спустя 14 минут, 32 секунды (31.08.2012 - 20:57) sergeiss написал(а):
olegod - тебе правильно говорят - надо изначально правильно спректировать БД, чтобы потом не кусать локти (с) Игорь_Vasinsky smile.gif

"Твой" вопрос уже неоднократно поднимался на форуме. И каждый раз приходили к тому, что надо просто использовать автокремент и не парить мозХ.

Спустя 21 минута, 20 секунд (31.08.2012 - 21:18) Игорь_Vasinsky написал(а):
rolleyes.gif бывают (всегда есть) ситуация - когда лень пересмотреть свой алгоритм и просит подмоги, чтоб собрать костыль, но костыль - от того и называется костылём - потому что он - костыль.

Спустя 5 часов, 41 минута, 26 секунд (2.09.2012 - 03:00) Alchemist написал(а):
Вообще, люди конечно правы, и такой задачи не должно возникать в принципе, но если принять её как теоретическое упражнение, то вот вариант:
SELECT a.field + 1 AS `empty` FROM `table` AS `a` LEFT JOIN `table` AS `b` ON (b.field = a.field + 1) WHERE b.field IS NULL ORDER BY a.field LIMIT 1

запрос проходит по таблице и для каждого значения поля ищет следущее по порядку. Как только не находит - останавливается и возвращает пропущеное значение.

Два условия чтобы запрос работал вменяемое время (<0.01 сек для 5к таблицы):

1) поле с числовыми значениями обязано быть индексом. (в идеале - уникальным)
2) ON условие должно быть записано именно так, как написал я (b = a + 1) и ни в коем случае не наоборот (a = b - 1)

Также, поскольку запрос ищет "следущее" значение относительно имеющегося, то проверка начинается с минимального значения в поле. Другими словами, если не будет строки с field = 1, запрос этого не увидит.

Спустя 7 часов, 1 минута, 48 секунд (2.09.2012 - 10:01) 123456 написал(а):
1) Берем 1
2) проверяем или есть в БД
3) есть - продолжаем. Нет - Записываем
4) прибавляем +1
5) проверяем или есть в БД id+1
6) есть - повторяем алгоритм с пункта 4. Нет - Записываем

Спустя 41 минута, 12 секунд (2.09.2012 - 10:43) Michael написал(а):
Цитата (123456 @ 2.09.2012 - 10:01)
1) Берем 1
2) проверяем или есть в БД
3) есть - продолжаем. Нет - Записываем
4) прибавляем +1
5) проверяем или есть в БД id+1
6) есть - повторяем алгоритм с пункта 4. Нет - Записываем

т.е. ты предлагаешь множественные запросы в цикле слать?

Alchemist, вот этот твой последний вариант - вполне рабочее решение такой задачи. А на значение 1 можно сперва и проверить.

Спустя 4 часа, 5 минут, 10 секунд (2.09.2012 - 14:48) sergeiss написал(а):
Цитата (123456 @ 2.09.2012 - 12:01)
1) Берем 1
2) проверяем или есть в БД
3) есть - продолжаем. Нет - Записываем
4) прибавляем +1
5) проверяем или есть в БД id+1
6) есть - повторяем алгоритм с пункта 4. Нет - Записываем

А если в таблице хотя бы 100К записей? Ты представляешь время работы твоего алгоритма?

Если уж очень хочется находить пропущенные (по причине удаления) значения, то решение есть. Но - только для удаленных величин!!! Надо просто записывать их в отдельную таблицу и выбирать оттуда первое попавшееся. И учти, что у тебя все равно ВСЕГДА будут пропуски при твоем алгоритме работы smile.gif Ну вот удалил ты несколько значений (допустим, 5, 7, 11). Потом создал одну новую запись (с величиной 5). А остальные-то значения (7, 11) остались не использованными.

Но еще раз повторю, что на самом деле
Цитата (sergeiss @ 31.08.2012 - 22:57)
каждый раз приходили к тому, что надо просто использовать автокремент и не парить мозХ.

Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.