Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Выборка нескольких случайных значений из MySQL 
:(
    Опции темы
console
  Дата 18.9.2007, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 307
Регистрация: 12.2.2007
Где: Belarus::Minsk

Репутация: 2
Всего: 3



Есть таблица... допустим там 200 записей. Мне нужно выбрать 5 случайных... Как это осуществить?


--------------------
user posted image
Nothing is impossible
My WeBlog
PM MAIL WWW ICQ   Вверх
BobiKK
Дата 18.9.2007, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 655
Регистрация: 1.12.2005
Где: Essen, Deutschlan d

Репутация: 4
Всего: 16



Код

SELECT * FROM `table` ORDER BY RAND() LIMIT 5

Быстро, но оптимизации никакой. Для таблицы в 200 записей, однако, не критично
PM MAIL   Вверх
console
Дата 18.9.2007, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 307
Регистрация: 12.2.2007
Где: Belarus::Minsk

Репутация: 2
Всего: 3



Спасибо, 200 не предел... будет много записей, как оптимизировать?


--------------------
user posted image
Nothing is impossible
My WeBlog
PM MAIL WWW ICQ   Вверх
BobiKK
Дата 18.9.2007, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 655
Регистрация: 1.12.2005
Где: Essen, Deutschlan d

Репутация: 4
Всего: 16



Оптимизировать тяжко. Можете почитать дискуссию здесь:
http://www.mysqlperformanceblog.com/2006/0...e-optimization/
Варианты там тоже имеются
PM MAIL   Вверх
console
Дата 18.9.2007, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 307
Регистрация: 12.2.2007
Где: Belarus::Minsk

Репутация: 2
Всего: 3



Составление оптимальных запросов целое искусство...


--------------------
user posted image
Nothing is impossible
My WeBlog
PM MAIL WWW ICQ   Вверх
console
Дата 19.9.2007, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 307
Регистрация: 12.2.2007
Где: Belarus::Minsk

Репутация: 2
Всего: 3



Здесь приведена хорошая статья по выборке случайных значений. Примеры идут для выбора одного случайного. В конце статьи автор предлагает пример функции для выборки произвольного количества.
Вопрос: не могут ли совпадать значения?
В MySQL reference пишется, что RAND() генерит числа от 0 до 1. В примере подсчитал, что кол-во знаков после запятой = 14. Насколько безопасно использование такого кода?

Код

DELIMITER $$
DROP PROCEDURE IF EXISTS get_rands$$
CREATE PROCEDURE get_rands(IN cnt INT)
BEGIN
  DROP TEMPORARY TABLE IF EXISTS rands;
  CREATE TEMPORARY TABLE rands ( rand_id INT );

loop_me: LOOP
    IF cnt < 1 THEN
      LEAVE loop_me;
    END IF;

    INSERT INTO rands
       SELECT r1.id
         FROM random AS r1 JOIN
              (SELECT (RAND() *
                            (SELECT MAX(id)
                               FROM random)) AS id)
               AS r2
        WHERE r1.id >= r2.id
        ORDER BY r1.id ASC
        LIMIT 1;

    SET cnt = cnt - 1;
  END LOOP loop_me;
END$$
DELIMITER ;

CALL get_rands(4);
SELECT * FROM rands;
+---------+
| rand_id |
+---------+
|  133716 |
|  702643 |
|  112066 |
|  452400 |
+---------+



--------------------
user posted image
Nothing is impossible
My WeBlog
PM MAIL WWW ICQ   Вверх
sTa1kEr
Дата 19.9.2007, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Цитата(console @  19.9.2007,  11:03 Найти цитируемый пост)
Вопрос: не могут ли совпадать значения?

Еще как могут, там никто и не обещает, что рандомные значения будут уникальные. Для гарантированной уникальности я бы немного модифицировал хранимку
Код

DELIMITER $$
DROP PROCEDURE IF EXISTS get_rands$$
CREATE PROCEDURE get_rands(IN cnt INT)
BEGIN
  DROP TEMPORARY TABLE IF EXISTS rands;
  CREATE TEMPORARY TABLE `rands` (`rand_id` INTEGER,  PRIMARY KEY (`rand_id`));
  IF (SELECT COUNT(*) FROM random) >= cnt THEN
loop_me: LOOP

    IF (SELECT COUNT(*) FROM rands) >= cnt THEN
      SELECT * FROM rands;
      LEAVE loop_me;
    END IF;

    INSERT IGNORE INTO rands
       SELECT r1.id
         FROM random AS r1 JOIN
              (SELECT (RAND() *
                            (SELECT MAX(id)
                               FROM random)) AS id)
               AS r2
        WHERE r1.id >= r2.id
        ORDER BY r1.id ASC
        LIMIT 1;
    -- SET cnt = cnt - 1;
  END LOOP loop_me;
  END IF;
END$$
DELIMITER ;

Дополнительная проверка нужна, что бы не было зацикливания, если параметр cnt больше общего количества строк.

Это сообщение отредактировал(а) sTa1kEr - 19.9.2007, 15:17
PM MAIL   Вверх
ewolf
Дата 19.9.2007, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 389
Регистрация: 15.8.2006
Где: г. Москва

Репутация: 8
Всего: 18



Вот что-то сомнительно мне, что данная хранимая процедура будет производительней одного SQL запроса
PM MAIL ICQ   Вверх
sTa1kEr
Дата 19.9.2007, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Цитата(ewolf @  19.9.2007,  15:49 Найти цитируемый пост)
Вот что-то сомнительно мне, что данная хранимая процедура будет производительней одного SQL запроса 

Зависит от структуры таблицы, количества записей в ней и количества необходимых рандомных значений, т.к. ORDER BY RAND() пересортировывает всю таблицу используя filesort. Для 100-200 записей, вероятно, эта хранимка действительно будет дольше работать, а вот для 1000000 ...

Если очень хочется одним запросом, то можно ускорить этот запрос следующим образом
Код

SELECT t.* 
FROM `table` t
INNER JOIN (SELECT `id` FROM `table` ORDER BY RAND() LIMIT 5) AS rnd ON t.`id` = rnd.`id`


Это сообщение отредактировал(а) sTa1kEr - 19.9.2007, 16:26
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0497 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.