2016-08-17 3 views
1

Учитывая эту таблицу изображений MYSQL, я хочу получить самые рейтинговые записи за каждый день.MYSQL - Найти 3 самых рейтинговых записи за каждый день

id created_at    rateScore 
-------------------------------------- 
1  2014-06-16 12:30:00 100 
2  2014-06-16 13:30:00 200 
3  2014-06-16 14:30:00 50  
4  2014-06-16 15:30:00 20 
5  2014-06-16 16:30:00 0 
6  2014-06-17 14:30:00 100 
7  2014-06-17 14:31:00 90 
8  2014-06-18 14:31:00 100 

Ожидаемый результат: Показать только 3 лучших по рейтингу изображений на каждый день.

id created_at    rateScore 
-------------------------------------- 
1  2014-06-16 12:30:00 100 
2  2014-06-16 13:30:00 200 
3  2014-06-16 14:30:00 50   
6  2014-06-17 14:30:00 100 
7  2014-06-17 14:31:00 90 
8  2014-06-18 14:31:00 100 

Я пробовал много с подборами и т. Д., Но я начинаю расстраиваться. Проблема кажется легкой, но ее трудно решить. Может быть, кто-то подскажет, как это решить.

Заранее спасибо и есть хороший день

+0

'SELECT * FROM таблицы WHERE created_at = 'дата' ORDER BY rateScore DESC LIMIT 0,3' – Derek

+1

Возможный дубликат из [Использование LIMIT внутри GROUP BY для получения N результатов для каждой группы?] (http://stackoverflow.com/questions/2129693/using-limit-within-group-by-to-get-n-results-per-group) –

+1

@You Это не сработает, потому что он хочет верхнюю 3 на _group_, а не весь набор результатов. –

ответ

0

Вы можете достичь результата с помощью MySQL user defined variables

SELECT 
t.id, 
t.created_at, 
t.rateScore 
FROM 
(
    SELECT 
    *, 
    IF(@sameDate = DATE(created_at), @rn := @rn + 1, 
     IF(@sameDate := DATE(created_at), @rn := 1, @rn := 1) 
    ) AS row_number 
    FROM your_table 
    CROSS JOIN (SELECT @sameDate := '0000-00-00', @rn := 1) var 
    ORDER BY created_at,rateScore DESC 
) AS t 
WHERE t.row_number <= 3 
ORDER BY t.created_at, t.rateScore DESC 

Для того, чтобы получить X записи на каждый день просто изменить эту строку (WHERE t.row_number <= 3), как показано ниже:

WHERE t.row_number <= X

Примечание: Я предполагаю, что составной индекс на (created_at,rateScore) будет играйте с повышением производительности.

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

ALTER TABLE `your_table` ADD INDEX `idx_table_creaed_at_rateScore` (
    `created_at`, 
    `rateScore` 
); 
+0

Это почти работает, только в sub выбирает ' ORDER BY DATE (created_at) 'был неправильным. Большое вам спасибо. Полный запрос выглядит следующим образом: 'SELECT t.id, t.created_at, t.rateScore FROM (SELECT *, IF (@sameDate = DATE (created_at), @rn: = @rn + 1, IF (@ sameDate: = DATE (created_at), @rn: = 1, @rn: = 1)) AS row_number FROM bombings CROSS JOIN (SELECT @sameDate: = '0000-00-00', @rn: = 1) var ORDER BY DATE (created_at), rateScore DESC) AS t WHERE t.row_number <= 3 ORDER BY DATE ('t'.'created_at') DESC, rateScore DESC' – madflanderz

+0

Это было не так. Кстати, рад слышать, что это сработало для вас. – 1000111

+0

Этот запрос требует 4 сек для всех 100000 записей, намного лучше, чем другое решение. – madflanderz

0

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

select * from tablename t1 
where (select count(*) from tablename t2 
     where DATE(t2.created_at) = DATE(t1.created_at) 
     and t2.rateScore > t1.rateScore) < 3 

Примечание: Вернется 4 строки, если есть галстук на третьем месте. (Например, 100, 80, 70, 70.)

+0

Спасибо, jarlh, это работает.Запрос mysql выглядит так: 'select * from bombings t1 где (выберите count (*) из взрывов t2, где DATE (t2.created_at) = DATE (t1.created_at) и t2.rateScore> t1.rateScore) <3 ORDER BY DATE (t1.created_at), t1.rateScore' – madflanderz

+0

Мне просто интересно, что, если есть более 3 записей? И 'и t2.rateScore> t1.rateScore' Я сомневаюсь в этом условии. Разве он не должен возвращать записи с самым низким уровнем тарифов? – 1000111

+0

Подзапрос подсчитывает количество строк с более высокой оценкой (в тот же день). Если из подзапроса возвращено более 3 строк, не возвращайтесь из t1. – jarlh

0

Пожалуйста, используйте ниже запрос

select r.* from rate as r 
where r.created_at IN 
(select group_concat(r1.id) from rate as r1 
where r1.created_at = r.created_at order by r1.rateScore 
desc limit 0,3) group by r.id 
+0

Хе-хе, это была моя первая попытка, но у меня была эта ошибка: # 1235 - Эта версия MySQL еще не поддерживает «LIMIT & IN/ALL/ANY/SOME subquery» – madflanderz

0

MySQL не хватает аналитики функций, в Funtionality вы ищете. Но вы можете найти workarround с использованием переменных. Что-то вроде:

SELECT id, 
     date, 
     rateScore 
    FROM (SELECT t.id, 
        t.date, 
        t.rateScore, 
        @curRank := IF([email protected]_date, @curRank + 1, @curRank := 1) AS rank, 
        @last_date := date 
     FROM  (SELECT * FROM table ORDER BY date) t, 
        (SELECT @curRank := 0) r) aux 
WHERE aux.rank <= 3 

Я действительно не тестировал запрос, но вы можете получить общую идею.

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