Уникальное число поколений 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 для этого, а не для сценариев. Чего вы пытаетесь достичь?