Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [MySQL] Случайная сортировка с условием, без использования RAND() 
:(
    Опции темы
Sanchezzz
Дата 17.8.2012, 06:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: нет
Всего: 60



Добрый день. Есть динамически составленный запрос который составляется через большую функцию впыхе которая на выходе выдает такое

Код

SELECT SQL_CALC_FOUND_ROWS ce.* , v1.value as `create_film` ce  FROM `cblock_element` 
INNER JOIN ( 
     SELECT * FROM cblock_type_value WHERE id_type_feald=8 AND id_lang=1 AND CAST(value as SIGNED)=2011
) v1 ON( v1.id_element = ce.id_element )
WHERE ce.`id_cblock_g` = 1 AND ce.parent_id IN (2,3,184,187,317,556,555,595,950,957) AND ce.is_dir=0
GROUP BY id_element
ORDER BY  ce.`sort` ASC , ce.time DESC
LIMIT 0,24


Условий может быть сколько угодно (до60) они добавляются в запрос примерно так 
Код
 INNER JOIN ( 
     SELECT * FROM cblock_type_value WHERE id_type_feald=8 AND id_lang=1 AND CAST(value as SIGNED)>=2000 and  CAST(value as SIGNED)<=2012 --итд ...
) v1 ON( v1.id_element = ce.id_element )


Cлучайная выборка выполняется с помощью варварского метода  ORDER BY RAND() хотелось бы переделать под элегантный быстрый вариант.
Подскажите как лучше реализовать случайную выборку

Это сообщение отредактировал(а) Sanchezzz - 17.8.2012, 06:59


--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
Akina
Дата 17.8.2012, 08:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


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

Репутация: 45
Всего: 454



Цитата(Sanchezzz @  17.8.2012,  07:57 Найти цитируемый пост)
Cлучайная выборка выполняется с помощью варварского метода  ORDER BY RAND()

Нормальный метод

Цитата(Sanchezzz @  17.8.2012,  07:57 Найти цитируемый пост)
хотелось бы переделать под элегантный быстрый вариант.

Элегантных вариантов масса. Но быстрый - не получится. SQL_CALC_FOUND_ROWS - а, значит, выборка всех записей, и никакой LIMIT не поможет.

Кстати, если inner join - нахрена вложенный селект?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Sanchezzz
Дата 17.8.2012, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: нет
Всего: 60



SQL_CALC_FOUND_ROWS только считает статистику сколько всего возможно было выбрано если не использовался лимит с ткущим условием выборки это быстрее чем тоже самое с count(*) в отдельным запросе. (я планирую его убирать при рандомных выборках + с лимитом начало позиции оставляя только просто LIMIT N )

И если мне не изменяет память от прочитаного когда то давно то SQL_CALC_FOUND_ROWS  в myIsam бреется из собственной хранения информации о таблице когда для InnoDB наоборот считается тем самым выполнения делается дольше но результат такой же.

Цитата

Кстати, если inner join - нахрена вложенный селект? 


Структура такая хранения данных о объекте в одной таблице ( Мусора ) 
выборка происходит по принцепу обращения к одной и тойже таблице много раз по условию которое строится по специальному объекту класса в пхп

1 критерия условия поиска по нужному полю
Код

$filter->setType('INNER' , 'create_film')>set('create_film' , '>' , 2011)->setAnd('create_film' , '<' , 2012)->setSort('create_film','DESC');

На выходе получаем часть фильтра который потом склеиваем с 2 и 3 куском фильтра в последовательности вызова.
Код

INNER JOIN ( 
     SELECT * FROM cblock_type_value WHERE id_type_feald=8 AND id_lang=1 AND CAST(value as SIGNED) > 2011 and CAST(value as SIGNED) < 2012
) v1 ON( v1.id_element = ce.id_element )

2 критерия поиска по другому полю
Код

$filter->setType('INNER' , 'ratind')>setDoSel()->set('ratind' , '>' , '0.9', '' , '' )->setOr('ratind' , '<' , '09')->setDoSelEnd();

на выходе получаем 
Код

INNER JOIN ( 
     SELECT * FROM cblock_type_value WHERE id_type_feald=7 AND id_lang=1 AND ( value > '09 ' OR value < '0.9' )
) v2 ON( v2.id_element = ce.id_element )


Эти 2 части запросов складываются в той последовательности в какой они были вызваны на выходе получаем полный запрос

Код

SELECT SQL_CALC_FOUND_ROWS ce.* , v1.value as `create_film`  v2.value as `ratind`   FROM `cblock_element` ce

INNER JOIN ( 
     SELECT * FROM cblock_type_value WHERE id_type_feald=8 AND id_lang=1 AND CAST(value as SIGNED)=2011
) v1 ON( v1.id_element = ce.id_element )

INNER JOIN ( 
     SELECT * FROM cblock_type_value WHERE id_type_feald=7 AND id_lang=1 AND ( value > '09 ' OR value < '0.9' )
) v2 ON( v2.id_element = ce.id_element )

WHERE ce.`id_cblock_g` = 1 AND ce.parent_id IN (2,3,184,187,317,556,555,595,950,957) AND ce.is_dir=0
GROUP BY id_element
ORDER BY  `create_film`DESC
LIMIT 0,24

Если есть решения как это написать лучше я посмотрю и почитаю с удовольствием,  но сразу скажу что SELF JOIN выборка не подходила под мои требования 

Это сообщение отредактировал(а) Sanchezzz - 17.8.2012, 10:33


--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
Akina
Дата 17.8.2012, 10:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


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

Репутация: 45
Всего: 454



Чем 
Код

select *
from a
inner join
(
select *
from b 
where b.x='1'
) с on a.y=с.y
where a.z='2'

отличается от
Код

select *
from a, b
where b.x='1' and a.y=b.y and a.z='2'

?




--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Sanchezzz
Дата 17.8.2012, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: нет
Всего: 60



Есть соображения пока только такие:
Обвернуть все в дополнительный SELECT b перенести rand() во временную таблицу с меньшим количеством данных
Код

 select * from (селект, условия выборки + ЛИМИТ N ) t1 ORDER BY RAND() 


Добавлено через 10 минут и 59 секунд
Цитата

отличается от
Код

select *
from a, b
where b.x='1' and a.y=b.y and a.z='2'

?

Нечем оба одинаково работаю за исключением того что мы не создаем лишнею временную таблицу


--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
Akina
Дата 17.8.2012, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


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

Репутация: 45
Всего: 454



Цитата(Sanchezzz @  17.8.2012,  11:39 Найти цитируемый пост)
мы не создаем лишнею временную таблицу 

Просил быстрее? используй.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




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


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

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