Уникальное число поколений mysql
Я хочу сгенерировать уникальное случайное целое число (от 10000 до 99999) только чистым mySQL; любые идеи?
Я не хочу генерировать это число в php путем циклирования (сгенерировать число → проверить его в базе данных), потому что я хочу использовать некоторое интеллектуальное решение в запросе mySQL.
Ответы
Ответ 1
Хотя это кажется несколько неудобным, это то, что можно сделать для достижения цели:
SELECT FLOOR(10000 + RAND() * 89999) AS random_number
FROM table
WHERE random_number NOT IN (SELECT unique_id FROM table)
LIMIT 1
Проще говоря, он генерирует N случайных чисел, где N - количество строк таблицы, отфильтровывает те, которые уже присутствуют в таблице, и ограничивает оставшееся значение равным единице.
Это может быть несколько медленным на больших таблицах. Чтобы ускорить работу, вы можете создать представление из этих уникальных идентификаторов и использовать его вместо вложенного оператора select.
EDIT: удаленные цитаты
Ответ 2
Создайте таблицу поиска из последовательных чисел для рандомизированных значений id в диапазоне от 1 до 1M:
create table seed ( i int not null auto_increment primary key );
insert into seed values (NULL),(NULL),(NULL),(NULL),(NULL),
(NULL),(NULL),(NULL),(NULL),(NULL);
insert into seed select NULL from seed s1, seed s2, seed s3, seed s4, seed s5, seed s6;
delete from seed where i < 100000;
create table idmap ( n int not null auto_increment primary key, id int not null );
insert into idmap select NULL, i from seed order by rand();
drop table seed;
select * from idmap limit 10;
+----+--------+
| n | id |
+----+--------+
| 1 | 678744 |
| 2 | 338234 |
| 3 | 469412 |
| 4 | 825481 |
| 5 | 769641 |
| 6 | 680909 |
| 7 | 470672 |
| 8 | 574313 |
| 9 | 483113 |
| 10 | 824655 |
+----+--------+
10 rows in set (0.00 sec)
(Все это занимает около 30 секунд для работы на моем ноутбуке. Вам нужно будет сделать это только один раз для каждой последовательности.)
Теперь у вас есть сопоставление, просто отслеживайте, сколько было использовано (поле ключа счетчика или auto_increment в другой таблице).
Ответ 3
Я боролся с решением здесь некоторое время, а затем понял, что он терпит неудачу, если столбец имеет NULL записи. Я переработал это со следующим кодом:
SELECT FLOOR(10000 + RAND() * 89999) AS my_tracker FROM Table1 WHERE "tracker" NOT IN (SELECT tracker FROM Table1 WHERE tracker IS NOT NULL) LIMIT 1
Загадайте здесь;
http://sqlfiddle.com/#!2/620de1/1
Надеюсь, что это полезно:)
Ответ 4
Единственная разумная идея на полпути, которую я могу придумать, - создать таблицу с конечным пулом идентификаторов, и поскольку они используются, удалите их из этой таблицы. Эти ключи могут быть уникальными и создать script для создания этой таблицы. Затем вы можете вытащить один из этих ключей, создав случайный выбор из доступных ключей. Я сказал "на полпути" разумно и честно, что это был путь к великодушию, но он случайным образом генерирует ключи, пока вы не создадите уникальный, я полагаю.
Ответ 5
Мое решение, реализованное в Cakephp 2.4.7, заключается в создании таблицы с одним полем auto_incremental type
CREATE TABLE `unique_counters` (
`counter` int(11) NOT NULL AUTO_INCREMENT,
`field` int(11) NOT NULL,
PRIMARY KEY (`counter`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Затем я создал функцию php, чтобы каждый раз вставлять новую запись, считывает сгенерированный идентификатор и удаляет его немедленно.
Статус Mysql хранится в памяти. Все генерируемые числа уникальны до тех пор, пока вы не выполните reset счетчик mysql или запустите команду TRUNCATE TABLE
найдите ниже модель, созданная в CakePHP, чтобы реализовать все
App::uses('AppModel', 'Model');
/**
* UniqueCounter Model
*
*/
class UniqueCounter extends AppModel {
/**
* Primary key field
*
* @var string
*/
public $primaryKey = 'counter';
/**
* Validation rules
*
* @var array
*/
public $validate = array(
'counter' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
);
public function get_unique_counter(){
$data=array();
$data['UniqueCounter']['counter']=0;
$data['UniqueCounter']['field']=1;
if($this->save($data)){
$new_id=$this->getLastInsertID();
$this->delete($new_id);
return($new_id);
}
return(-1);
}
}
Любые проверки диапазона принадлежности результата могут быть реализованы в одной и той же функции, манипулируя полученным результатом
Ответ 6
Функция RAND() генерирует случайное число, но не гарантирует уникальность. Правильный способ обработки уникальных идентификаторов в MySQL - объявить их с помощью AUTO_INCREMENT.
Например, поле id в следующей таблице не нужно будет указывать на вставках, и оно всегда будет увеличиваться на 1:
CREATE TABLE animal (
id INT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
);
Ответ 7
Я попытался использовать этот ответ, но для меня это не сработало, поэтому мне пришлось немного изменить исходный запрос.
SELECT FLOOR(1000 + RAND() * 89999) AS random_number
FROM Table
WHERE NOT EXISTS (SELECT ID FROM Table WHERE Table.ID=random_number) LIMIT 1
Ответ 8
Создайте уникальный индекс в поле, где вы хотите уникальный случайный #
Затем запустите
Update IGNORE Table
Set RandomUniqueIntegerField=FLOOR(RAND() * 1000000);
Ответ 9
Я беспокоюсь о том, почему вы хотите это сделать, но вы можете просто использовать:
SELECT FLOOR(RAND() * 1000000);
Для получения дополнительной информации см. полную документацию по MySQL RAND.
Однако я надеюсь, что вы не используете это как уникальный идентификатор (используйте атрибут auto_increment в достаточно большом беззнаковом целочисленном поле, если это это то, что вам нужно), и мне нужно задаться вопросом, почему вы используете MySQL для этого, а не для сценариев. Чего вы пытаетесь достичь?