PDA

Просмотр полной версии : [Function] Поиск наименьшего свободного значения для столбца [GetFreeTableNumber]



DeimoS
29.12.2016, 21:44
Описание:

Функция отправляет запрос в указанную таблицу и возвращает наименьшее свободное значение указанного столбца.
Возьмём в пример таблицу с аккаунтами "account", в которой есть столбец "id", хранящий в себе порядковый номер аккаунта и имеющий атрибут "AUTO_INCREMET".

Сейчас в таблице имеются 5 аккаунтов:


idplayer_name
1Vasya_Pupkin
2Nagibator_1337
4My_Name_Is_Skrillex
5SuperScripter
7MamaHeXotelLa_5a5aHeCtapalLc9


Если мы попробуем создать новый аккаунт, он автоматически создастся под ID 8 (если Вы не трогали настройки AUTO_INCREMENT).
Но представим, что нам, по какой-либо причине, аккаунт нужно создать под свободным ID (3 и 6), а не под самым большим.
Вот тут и пригодится эта функция, которая в как раз и вернёт значение "3".


Параметры:

const tablename[20] - Название таблицы, в которой будет происходить поиск (по умолчанию, максимальный размер - 20 символов. Можно увеличить/уменьшить)
const columnname[20] - Имя столбца, в котором будет происходить поиск свободного ID (по умолчанию, максимальный размер - 20 символов. Можно увеличить/уменьшить)


Возвращаемое значение:

Первое свободное значение, начиная с 1.

Код:



stock GetFreeTableNumber(const tablename[20], const columnname[20])
{
new query_string[106+(sizeof(columnname)*4)+(sizeof(tablename)*2)+1],
free_id;

format(query_string, sizeof(query_string), "SELECT MIN(%s) AS free_id FROM %s", columnname, tablename);
new Cache:result = mysql_query(mysql_connect_ID, query_string);
cache_get_value_name_int(0, "free_id", free_id);
cache_delete(result);

if(free_id != 1)
return 1;
else
{
format(query_string, sizeof(query_string), "SELECT %s+1 AS free_id FROM %s AS a1 WHERE (SELECT 1 FROM %s AS a2 WHERE a2.%s=a1.%s+1) IS NULL ORDER BY a1.%s LIMIT 1", columnname, tablename, tablename, columnname, columnname, columnname);
result = mysql_query(mysql_connect_ID, query_string);
cache_get_value_name_int(0, "free_id", free_id);
cache_delete(result);
return free_id;
}
}


Примечание:

Крайне НЕ рекомендуется использовать данную функцию для больших таблиц (таблиц, с большим числом строк).
Поиск свободного ID производится путём перебора значений от минимального к максимального и, допустим, если у Вас в таблице более миллиона записей, сами понимаете, запрос может обрабатываться приличное количество времени.
Поэтому если и потребуется использовать данную функцию для больших таблиц, постарайтесь минимизировать частоту вызовов этой функции (не стоит её пихать в секундный таймер, если не хотите проблем).

Автор:

DeimoS

Salik_Davince
29.12.2016, 23:51
Большое спасибо, уж очень долго сам перечитывал документацию но не находил выход для A_I.

ziggi
30.12.2016, 00:05
Но представим, что нам, по какой-либо причине, аккаунт нужно создать под свободным ID (3 и 6), а не под самым большим.
Вот тут и пригодится эта функция, которая в как раз и вернёт значение "3".

Честно говоря, ума не приложу кому такое может придти в голову. Если кто-то будет использовать - напишите для чего, интересно.

DeimoS
30.12.2016, 01:45
Честно говоря, ума не приложу кому такое может придти в голову. Если кто-то будет использовать - напишите для чего, интересно.

Это был лишь пример, который первый в голову пришёл. Не самый удачный, но самый понятный для большинства, как мне кажется :)

Я писал эту функцию для таблицы с рангами для админов.
Точнее, я писал систему, позволяющую создавать ранги прямо из игры и номер строки в таблице означал уровень админки.
Но чтоб каждый раз не писать этот уровень самостоятельно и не держать существующие номера в голове, я добавил возможность не указывать его и тогда уже эта функция сама подберёт свободный ID.
Если просто использовать AUTO_INCREMENT, то будет как-то глупо выглядеть, если всего будет 10 рангов, но их уровни будут, например, "1", "5", "13", "14", "22" и т.п.

ziggi
30.12.2016, 07:28
Точнее, я писал систему, позволяющую создавать ранги прямо из игры и номер строки в таблице означал уровень админки.
Но чтоб каждый раз не писать этот уровень самостоятельно и не держать существующие номера в голове, я добавил возможность не указывать его и тогда уже эта функция сама подберёт свободный ID.
Если просто использовать AUTO_INCREMENT, то будет как-то глупо выглядеть, если всего будет 10 рангов, но их уровни будут, например, "1", "5", "13", "14", "22" и т.п.

Как по мне ID (private key) - это исключительно внутренняя информация, и его вообще нигде не нужно отображать. Можно было просто создать поле для обозначения уровней.

vovandolg
30.12.2016, 09:35
Честно говоря, ума не приложу кому такое может придти в голову. Если кто-то будет использовать - напишите для чего, интересно.

Авто удалению старых аккаунтов на глобальном проекте и их заменой на новые такая система пригодилась бы.
Не всегда же охота ковыряться в бд с несколькими тысячами аккаунтов и перебирать их отсеивать там удалять,
вот она автоматизированная система, не много нагрузки только прибавится.

Daniel_Cortez
30.12.2016, 10:32
Авто удалению старых аккаунтов на глобальном проекте и их заменой на новые такая система пригодилась бы.
Не всегда же охота ковыряться в бд с несколькими тысячами аккаунтов и перебирать их отсеивать там удалять,
вот она автоматизированная система, не много нагрузки только прибавится.
Что мешает просто периодически удалять все аккаунты, с которых заходили более N дней назад?

DeimoS
30.12.2016, 10:36
Как по мне ID (private key) - это исключительно внутренняя информация, и его вообще нигде не нужно отображать. Можно было просто создать поле для обозначения уровней.

Я изначально немного солгал, ибо забыл как всё было устроено :D
Как раз столбец, обозначающий номер строки, никак не "фильтруется" со стороны сервера и его определяет лишь БД.
Для номера ранга имеется отдельный столбец, который я как раз и форматировал этой функцией.
http://i.imgur.com/BL4If9s.png
Потом придумал совсем дугой алгоритм работы админки, а тот скрипт забросил.
Форматировался столбец с именем "rank_id"

- - - Добавлено - - -


Что мешает просто периодически удалять все аккаунты, с которых заходили более N дней назад?

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