2015-01-30 3 views
0

у меня возникают проблемы с пониманием, как решить, казалось бы, простая задача сортировки результатов ..MySQL сравнить, подсчет и порядок по

Я хочу, чтобы сравнить, сколько других пользователей, как те же фрукты, как как пользователь с ID 1, счетчик, который имеет большинство совпадений и отображает результаты в порядке убывания.

пользователей:

1 jack 
2 john 
3 jim 

фрукты:

id, title 
1 apple 
2 banana 
3 orange 
4 pear 
5 mango 

отношения: 2 индексов (user_id, fruit_id) и (fruit_id, user_id)

user_id, fruit_id 
1  1 
1  2 
1  5 
2  1 
2  2 
2  4 
3  3 
3  1 

Ожидаемые результаты: (по сравнению с Любимые фрукты Джека (user_id = 1))

user_id, count 
1   3 
2   2 
3   1 

Запрос:

SELECT user_id, COUNT(*) AS count FROM relations 
WHERE fruit_id IN (SELECT fruit_id FROM relations WHERE user_id=1) 
GROUP BY user_id 
HAVING count>=2 

Больше "оптимизированы" запроса:

SELECT user_id, COUNT(*) AS count FROM relations r 
WHERE EXISTS (SELECT 1 FROM relations WHERE user_id=1 and r.fruit_id=fruit_id) 
GROUP BY user_id 
HAVING count>=2 

2 минимальное число совпадений. (Требуется для будущего)

объяснить:

id select_type   table  type possible_keys key  key_len  ref     rows Extra 
1 PRIMARY    r   index NULL   uid  8   NULL    15  Using where; Using index 
2 DEPENDENT SUBQUERY relations eq_ref xox,uid   xox  8   r.relations,const 1  Using where; Using index 

Все работает отлично, пока я пытаюсь использовать ORDER BY DESC счета

Тогда я вижу: Использование временного; Использование filesort

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

Я знаю, именно так определяется SQL и как он работает. Но я не могу понять, как это сделать по-другому? Без временных таблиц и filesort.

Мне нужно показать пользователей, у кого больше всего совпадений.

Пожалуйста, помогите мне.

UPD: Я провел несколько тестов с запросом от Уокера Фарроу (который по-прежнему использует файловый порт).

20,000 rows - avg 0.05 seconds 
120,000    0.20 sec. 
1,100,000   2.9 sec. 

Неутешительные результаты. Можно было бы изменить структуру таблиц, но при таком подсчете и сортировке я не знаю, как это сделать.

Есть ли какие-либо предложения о том, как это можно сделать?

+0

Ну, вы можете переключить механизм сортировки в части языка программирования, если это не проблема. – Prateek

+0

Да, было бы легко, если бы было небольшое количество результатов. Проблема заключается в количестве пользователей - количестве совпадений. Отображение данных по нескольким страницам ... –

+0

Ну, может быть, этот ответ может помочь вам [Оптимизация SQL-запросов во избежание временной таблицы] (http://stackoverflow.com/questions/11896271/sql-query-optimization-to-avoid-temporary -Таблица). – Prateek

ответ

0

Вероятно, лучший способ сделать это было бы создать подзапрос, а затем приказать в внешнем запросе, что-то вроде этого:

select * 
from (
    SELECT user_id, COUNT(*) AS count FROM relations r 
    WHERE EXISTS (SELECT 1 FROM relations WHERE user_id=1 and r.fruit_id=fruit_id) 
    GROUP BY user_id 
    HAVING count(*)>=2 
    ) x 
order by count desc 

Кроме того, я не знаю, почему вам нужно добавить exists.Можете ли вы сказать следующее:

select * 
from (
    SELECT user_id, COUNT(*) AS count FROM relations r 
    WHERE user_id=1 
    GROUP BY user_id 
    HAVING count(*)>=2 
    ) x 
order by count desc 

?

Я не уверен, может быть, я чего-то не хватает. Надеюсь, это поможет!

+0

У меня есть вопрос о первом запросе, объяснить: 'ID \t SELECT_TYPE \t стол \t типа \t possible_keys \t ключ \t key_len \t реф \t строки \t Extra ОСНОВНОЙ \t ALL \t NULL \t \t NULL NULL \t \t NULL \t \t 3 Использование FileSort DERIVED \t г \t \t Индекс NULL \t \t \t UID 8 \t \t NULL 15 \t Используя где; Используя индекс Д. подзапрос \t отношения \t \t eq_ref XoX, Uid \t \t \t XoX 8 \t r.relations 1 \t Использование index' поэтому он с помощью "FileSort" по результатам (3 строки). Может ли это «использование filesort» быть проблемой в будущем, когда БД будет расти, скажем, 50 миллионов строк? –

+0

О втором запросе. Это неправильно, потому что он учитывает только любимые плоды Джона (id: 1). Нам нужно сравнить их с остальными - у кого похожие. Здесь ive нашла, как оптимизировать мой первый запрос (с оператором IN) [Оптимизация подзапросов с помощью стратегии EXISTS] (http://dev.mysql.com/doc/refman/5.0/en/subquery-optimization-with-exists .html) –

Смежные вопросы