SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 24.08.2009 18:09:00

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Выборка случайных значений из двух таблиц.

Опять я и с новой темой.
Имеем таблицы  t1 и t2

из одной таблицы выбираем случайные значения вот таким образом:

SELECT * FROM t1 JOIN ( SELECT CEIL(RAND() * ( SELECT MAX(id) FROM t1 )) AS randomID ) AS random_table ON t1.ID >= random_table.randomID LIMIT 20


А как сделать чтобы выборка была одновременно из двух таблиц?
Заранее спасибо.

Отредактированно Doxtor (24.08.2009 18:09:52)

Неактивен

 

#2 24.08.2009 18:25:43

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

Что-то типа этого???

SELECT * FROM t1 JOIN ( SELECT CEIL(RAND() * ( SELECT MAX(id) FROM t1 )) AS randomID ) AS random_table ON t1.ID >= random_table.randomID
UNION
SELECT * FROM t2 JOIN ( SELECT CEIL(RAND() * ( SELECT MAX(id) FROM t2 )) AS randomID ) AS random_table ON t2.ID >= random_table.randomID
LIMIT 10;

Неактивен

 

#3 24.08.2009 18:27:54

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

Честно говоря, не понял вопроса. Что значит — «одновременно из двух таблиц»?
У них одинаковые структуры? Почему тогда две таблицы?

Неактивен

 

#4 24.08.2009 18:30:30

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

Ахаа, пока писал — вы дописали... ну, именно так, только еще скобки поставить
(SELECT ... UNION SELECT ... ) LIMIT 10;

Только тормозить будет совершенно бессовестно.

Обычно делают SELECT ID ORDER BY RAND() LIMIT 10 и к нему потом прицепляют
сбоку основные данные. На не очень длинных таблицах работает.

И вопрос «почему тогда две таблицы» таки в силе smile

Неактивен

 

#5 24.08.2009 18:42:22

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

1. Со скобками не работает.
Пишет: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION

2. SELECT ID ORDER BY RAND() LIMIT 10  медленнее же работает вроде. Поменьшей мере без UNION

3. В разных таблицах лежат разные типы материала и поэтому так проще администрировать.

Неактивен

 

#6 24.08.2009 18:57:14

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

1. Да, мне казалось, что он понимает LIMIT после скобок — ан нет, прийдется дописать до
подзапроса.

2. Зато Ваш вариант выбирает одно случайное значение, и 10 ссылок после него — кажется,
это не совсем случайно уже wink

3. Мне казалось, что добавить поле проще — ну, кому как нравится. UNION всегда работают
хуже, чем дополнительное поле.

--

А вообще, это всегда сложная тема. Обычно если таблицы небольшие, то ORDER BY RAND()
от ID работает достаточно быстро. Если таблицы большие, то как правило достаточно взять
последние 1000 записей и выбирать RAND среди их ID.

Неактивен

 

#7 24.08.2009 19:14:04

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

Да похоже придётся делать через SELECT ID ORDER BY RAND()
Но как выбрать из двух таблиц не пойму никак.
Помогите составить запрос, позалуйста.

Отредактированно Doxtor (24.08.2009 19:14:44)

Неактивен

 

#8 24.08.2009 19:15:51

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

Никак, у Вас же ID пересекаются в разных табличках. Нужно или принять
условие «пять из этой таблички и пять из этой», или рандомизировать вместе
с данными sad

Неактивен

 

#9 24.08.2009 19:23:21

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

рандомизировать вместе с данными???
Это как?
Может я не совсем правильно выразился: нужно просто взять все поля из t1 и все поля из t2, их перемешать и вывести с LIMIT N
Могу сделать разные id в разных таблицах

Отредактированно Doxtor (24.08.2009 19:25:17)

Неактивен

 

#10 24.08.2009 20:34:03

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

Пусть у Вас есть таблица из всего двух столбцов — номер и данные (id + data).
id занимает 4 байта, ибо это число. data занимает много больше памяти (например,
пусть это будет 100 байт — не такое большое значение). А теперь внимание — строк
1000 штук. Для того чтобы выбрать 10 штук id методом ORDER BY RAND(), нужно
отсортировать 4 килобайта данных в памяти. Для того, чтобы «взять все поля из»
и выбрать те же 10 строк, нужно отсортировать в памяти 100 килобайт данных!

Может, разница кажется и не такой большой, но на большом количестве запросов
это сильно сказывается. А если учесть, что реальные данные обычно более 100
символов в данных, если сортировать «в лоб», то Вы начинаете сортировать мегабайты
информации для того, чтобы получить выжимку из 200-300 байт.

Неактивен

 

#11 25.08.2009 14:42:56

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

Обьединение таблиц отменяется.
Будем выбирать из одной.

По поводу вашего комментария...
Да...это понятно.
Но я ведь всё равно должен выбрать всё из таблицы     SELECT * FROM table ORDER BY rand()
Т.к. выводить я хочу именно data, а не id
Или я не прав?

Неактивен

 

#12 25.08.2009 14:58:16

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

Вам нужно получить 10 значений data, но при этом не нужно сортировать их — это
будет неэкономно по ресурсам. Гораздо эффективнее отсортировать id, выбрать
оттуда 10 штук, а потом по этим id найти данные. Это тот случай, когда самообъединение
таблицы увеличивает производительность запроса.

SELECT t1.data
FROM tablename t1
JOIN (SELECT id FROM tablename ORDER BY RAND() LIMIT 10) t2 USING (id);

Неактивен

 

#13 25.08.2009 15:25:08

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

Ничего не имею против экономии ресурсов.

Если я правильно вас понял, то в этом случае необходимо иметь две идентичные таблицы?!
Или как долзны выглядеть эти таблицы?

Неактивен

 

#14 25.08.2009 15:54:08

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

Нет, одной таблицы хватит. Самообъединение — на то и само, чтобы объединять
одну таблицу с самой собой (см пример выше).

Неактивен

 

#15 26.08.2009 15:44:44

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

Огромное спасибо разобрался:
имеем таблицу t1 с колонками id и data
запрос выглядит вот так

SELECT t1.data
FROM t1
JOIN (SELECT id FROM t1 ORDER BY RAND() LIMIT 200) t2 USING (id);


t2 - это временная таблица.

Я правильно понимаю, что скорость запроса и количество перегоняемых данных не всегда прямо пропорциональны?
Т.к. время вaшего запроса больше чем   
SELECT * FROM table ORDER BY rand();

Отредактированно Doxtor (26.08.2009 15:45:43)

Неактивен

 

#16 26.08.2009 15:53:59

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

Хм, так быть не должно wink ключик на id есть? Вам и правда нужно 200 значений?

Неактивен

 

#17 26.08.2009 16:04:06

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

Первичный ключ есть.
200 - для примера.

Неактивен

 

#18 26.08.2009 16:19:18

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

А explain от этого запроса покажите, пожалуйста

Неактивен

 

#19 26.08.2009 19:08:42

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

id     select_type     table                  type             possible_keys       key                 key_len        ref       rows     Extra
1     PRIMARY        <derived2>        ALL                     NULL              NULL              NULL              NULL      200     
1     PRIMARY         g_rattan           eq_ref             PRIMARY              PRIMARY          4                 t2.id         1     
2     DERIVED         g_rattan             index             NULL              PRIMARY                4               NULL      330     Using index; Using temporary; Using filesort

Отредактированно Doxtor (26.08.2009 19:12:39)

Неактивен

 

#20 26.08.2009 19:24:57

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

Кошмар и ужас! smile Выбирать 200 строк из 300 рандомно — по индексу дольше, да smile

Неактивен

 

#21 27.08.2009 11:54:23

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

Ну, я же для примера.
И в этом конкретном случае рэндом необходим.
Если ничего нельзя сделать, то ничего, результатом я всёравно доволен.
Большое спасибо за помощь.

Отредактированно Doxtor (27.08.2009 11:57:02)

Неактивен

 

#22 27.08.2009 13:14:11

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выборка случайных значений из двух таблиц.

Эм, объясню, что мне не нравится в числе 200.

Данные из таблиц забираются путем чтения их с диска. Как известно, читать с диска
последовательно — быстрее, чем читать из разных частей диска (передвижение головки
по диску — seek — это дорогая операция). Поэтому в данном случае оказывается, что
вытащить все данные с диска последовательно и отсортировать в памяти — быстрее, чем
вытащить данные точечно, уже сортированные (но с помощью seekов).

Обычная ситуация — вытащить случайные 5 строк из тысячи, например. Безусловно,
вытащить 5 случайных строк куда быстрее, чем прочитать и отсортировать 1000. В Вашем
же случае, Вы достаете 200 записей из 300.

Это я все к тому, что когда табличка разрастется, способ начнет давать свои преимущества.
Если же Вы всегда планируете доставать большую часть таблицы, то нужно действительно
доставать все, и со всеми данными уже играть в памяти.

Неактивен

 

#23 27.08.2009 13:33:20

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Выборка случайных значений из двух таблиц.

Ещё раз спасибо за компетентный ответ. Буду иметь в виду
Пока разница в скорости минимальная, но буду следить.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson