![]() |
|
Модераторы: skyboy |
![]()
|
|
| ST_Falcon |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 330 Регистрация: 14.11.2003 Где: Львов Репутация: нет Всего: 1 |
перелопатил поиск в поисках ответа на свой вопрос... но по моему все не то.
у меня есть две таблицы categories и images. в одной список категорий. в другой список изображений. связь по id категории. то есть каждое изображение принадлежит одной из категорий. задача: вывести по одному случайному изображению из каждой категории. как то можно такое организовать одним запросом? |
|||
|
||||
| Anark1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 622 Регистрация: 15.12.2006 Где: RF -> Moscow Репутация: нет Всего: 11 |
||||
|
||||
| SelenIT |
|
|||
![]() баг форума ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3996 Регистрация: 17.10.2006 Где: Pale Blue Dot Репутация: 6 Всего: 401 |
Да просто сгруппировать по id категории. Они и так будут достаточно случайными...
-------------------- Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму! |
|||
|
||||
| ST_Falcon |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 330 Регистрация: 14.11.2003 Где: Львов Репутация: нет Всего: 1 |
SelenIT,
по моему если группировать по id категории, тогда результаты всех запросов будут одинаковы. Anark1, это для выборки одной случайной записи. моя же ситуация описана выше. зы. пока сделал несколько запросов которые выбирают одну случайную запись для каждой категории. |
|||
|
||||
| sTa1kEr |
|
|||
|
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 7 Всего: 146 |
Но при этом каждый раз одинаковыми. ST_Falcon, В принципе можно вытащить строки из рандомно отсортированной таблицы images с группировкой по id категории, как и предложил SelenIT, но, имхо, это плохой стиль (поле id картинки будет без группировки и без вычисляемой функции)... Можно попробовать написать хранимку, которая будет проходить циклом по категориям и добавлять во временную таблицу случайное id каждой картинки. Ну и еще вариант. Добавить для таблицы картинок некое поле order, которое будет пронумеровать строки с сортировкой по id категории при каждом изменении таблицы images (или каждый раз пронумеровать при помощи переменной). Тогда можно будет одним запросом с группировкой выбрать случайные картинки по алгоритму: FLOOR(MIN(`order`) + RAND() * (MAX(`order`) - MIN(`ORDER`))) |
|||
|
||||
| ST_Falcon |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 330 Регистрация: 14.11.2003 Где: Львов Репутация: нет Всего: 1 |
sTa1kEr,
пробовал. в таблице изображений 20000 записей. запрос с сортировкой по RAND() выполнялся около минуты...
не очень понял. что значит "которое будет пронумеровать строки с сортировкой по id категории при каждом изменении таблицы images (или каждый раз пронумеровать при помощи переменной)"? делать еще один индекс картинок для каждой из категорий? 1я категория order от 0 до count(картинок в первой категории) 2z категория order от 0 до count(картинок в второй категории) так? |
||||
|
|||||
| sTa1kEr |
|
|||
|
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 7 Всего: 146 |
Нет. Не совсем. 1я категория от 1 до count(картинок в первой категории). 2ая от count(картинок в первой категории) + 1 до count(картинок в второй категории) и т.д. Т.е. что бы таблица images была гарантированно пронумерована от 1 до count(всего картинок). Тогда при групповом запросе можно получить гарантированно существующий случайный номер строки. |
|||
|
||||
| sTa1kEr |
|
||||
|
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 7 Всего: 146 |
Вот такой вот 3х этажный запрос получился. Если колонку `order` обновлять при каждом INSERT-е/UPDATE-е (можно на триггер повесить эту задачу), то SELECT очень сильно упростится - можно будет выкинуть два подзапроса и переменные. Добавлено через 2 минуты и 43 секунды
Такой будет запрос если при обновлении простовлять `order` |
||||
|
|||||
| muzer |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
sTa1kEr, позволю заметить очень большой минус решения: если на триггер повесить обновление order, то это означает апдейт в среднем 50% строк при каждой вставке новой записи (в среднем вставляем в середину, значит двигаем всех кто выше), в решении без триггера - два раза сортировка всех строк при каждом select'е.
Хочу предложить тоже не идеальный, но вариант. Таблицу images сделать примерно такой:
Запрос: 1) сначала вычисляется рэндом от или очень большого числа или от SELECT COUNT(*) FROM images. Операция пустяковая. 2)
Подзапрос выполняется достаточно быстро за счёт использования индекса, join соответственно тоже. |
||||
|
|||||
| sTa1kEr |
|
||||||
|
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 7 Всего: 146 |
Расчет быд на то, что INSERT-ы *значительно* реже SELECT-ов.
Решение без триггера я больше привел для примера, что бы сразу можно было бы потестить как оно работает. 1. Тогда уж "вычисленный_рэндом % MAX(ID) + 1" иначе теряется первая картинка (вместе со всей категорией). 2. Мы жестко привязываемся к движку MyISAM со всеми вытекающими. 3. Если картинка будет удалена, то образуется "пустота". И если вычислить именно этот несуществующий ID, то мы при запросе потеряем всю категорию! Что *значительно* хуже, чем дополнительный апдейт на пол таблицы. Но вы навели на мысль. Создаем примерно такой триггер на вставку
А после удаления пересчитываем order для категории. И соответственно запрос будет
Или же, как вы предложили, через остаток по делению, но, имхо, так намного хуже случайность выбора будет. |
||||||
|
|||||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | MySQL | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |