Выборка псевдо-случайных данных...

SeaGull

Junior Member
Выборка псевдо-случайных данных...

В базе есть несколько групп товаров (мониторы, принтеры, сканеры...)
Нужно случайным образом выбрать по 1 штуке товара (id и title) из каждой группы.

select id, title from catalog group by grp order by rand();
выдает всегда один и тот же набор данных. Только сортирует их от RND.

Подскажите пожалуйста, как правильно записать требуемый запрос.
 

Demiurg

Guest
попробуй так:
select distinct id, title from catalog order by rand();
 

SeaGull

Junior Member
Не, это совсем не то.
А группы-то где ?
Нужно что-бы в выборке каждая группа (grp) встречалась только один раз.
 

SeaGull

Junior Member
Да ну, разве так можно ?
По-моему, DISTINCT не может быть адресован только какому-то одному полю из списка...
...
Вот и MySQL (3.23) говорит, что нельзя:
ERROR 1064: You have an error in your SQL syntax near 'distinct grp from catalog' at line 1
 

Апельсин

Оранжевое создание
По стандарту GROUP BY выдает первое найденное, а сортировка применяется уже к самой выборке.
Так что да - невозможно, если я правильно поняла то что ты хочешь.
 

SeaGull

Junior Member
Спасибо.

Жаль. Значит придется разбивать процесс на 2 запроса.
 

ForJest

- свежая кровь
Можно и одним запросом на выборку, если правильно организовать таблицу.
<предварительные действия>
1. Ты добавляешь в таблицу поле rand_sort.
2. Задаешь множитель, заведомо больший, чем максимально возможное количество товаров в любой группе. Пусть это будет 2048
3. Дальше делаешь UPDATE table1 SET sort_rand = RAND()*2046+1;
4. В каждой группе первому первому товару присваиваешь 0, второму - 2048
</предварительные действия>
Дальше выбираешь случайным образом id товаров.
[sql]
SET @list_items := '', @passed_grp := '_', @criterion := RAND()*2048;

SELECT IF(@passed_grp LIKE CONCAT('%_',grp, '_%') OR rand_sort > @criterion, '', (@list_items:=CONCAT(@list_items, '(', id, ',', grp, ')')) AND (@passed_grp: = CONCAT(@passed_grp, grp, '_')) AND @criterion=RAND()*2048)FROM table1;

SELECT @list_items;
[/sql]
В итоге получаешь что-то типа
(10,1)(30,2)(44,3) - однострочную запись выборки - id товара, группа товара. По желанию можно расширить набор возвращаемых полей.
Данный метод тебе обеспечит фуллскан таблицы. Но один раз. И данные будут возвращены именно те, что тебе требуются.
Альтернативные методы
a) 1+N запросов со случайной выборкой товара в каждой группе
b) выбрать стоблцы id и grp всей таблицы и занятся выбором случайных с помощью PHP
У кого есть еще идеи по реализации этой задачи - прошу высказаться.
 

ForJest

- свежая кровь
Хотя при здравом размышлении пункт 4 предварительной подготовки делать не нужно.
[sql]
SELECT @list_items list_items, REPLACE(MID(@passed_grp, 2, LENGTH(@$passed_grp)-2), '_', ',') passed_grp;
[/sql]
потом делаешь
$passed_grp = $result['passed_grp'];
[sql]
select id, title from catalog WHERE grp NOT IN ($passed_grp)group by grp
[/sql]
Чтобы получить значения для тех групп, которые не были найдены указанным в предыдущем посте способом.
 
Сверху