Вывод строк с максимальным значением

aliokero

Как правильно изменить запрос так, чтобы в колонке subject выводились строки с максимальным значением views?

SELECT e.subject, e.tid AS thread_id, Date(e.time) AS arch_time
FROM entries e
WHERE e.pid = 0
GROUP BY Date(e.time)
ORDER BY arch_time DESC
LIMIT 0, 20
2 ответа

aliokero

SELECT subject, thread_id, arch_time FROM ( SELECT e.subject,e.tid AS thread_id,Date(e.time) AS arch_time, @n:=if(@ldt=Date(e.time),@n+1,1) N, -- N=1 если у пред. строки была другая дата -- N=N+1 если дата такая же как в предыдущей @ldt:=Date(e.time) -- Запоминаем дату, для проверки в след. записи FROM entries e,(select @ldt:=NULL,@n:=0) A WHERE e.pid = 0 ORDER BY Date(e.time) DESC,e.views DESC ) A WHERE N=1
LIMIT 0, 20

Используем переменные. @ldt помнит какая дата была у предыдущей записи, @n считает записи с конкретной датой с 1. Так как все данные отсортированы по дате и views в обратном порядке, то на каждую дату у записи с максимальным views N=1. Группировка происходит сама собой, без group by т.к. мы явно выбираем по одной записи для каждой даты.

Если бы нам была нужна только одна колонка (subject) для записи с максимальным views, т.е. e.tid был бы не нужен, то я бы предложил такой вариант:

select substr(max(concat(lpad(e.views,12,'0'),e.subject)),13) as subject, Date(e.time) AS arch_time from entries e where e.pid=0 group by Date(e.time) order by arch_time DESC limit 0, 20

тут фокус в том, что мы собираем строки вида 000000000123SUBJECT, где ведущие цифры это views, берем от этого поля max, получая таким образом значение с максимальным views и вырезаем из него обратно интересующую нас информацию. В принципе можно применить этот подход и для нескольких колонок, но это неудобно, когда их много


aliokero

Погуглите или здесь

В MySQL такая задача выполняется в два этапа:

  1. Следует получить список (изделие, максимальная цена)

  2. Для каждого изделия, получить соответствующие записи, в которых цена соответствует максимальной.

Это легко делается с помощью временной таблицы:

CREATE TEMPORARY TABLE tmp ( article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, price DOUBLE(16,2) DEFAULT '0.00' NOT NULL);
LOCK TABLES shop read;
INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article;
SELECT shop.article, dealer, shop.price FROM shop, tmp
WHERE shop.article=tmp.article AND shop.price=tmp.price;
UNLOCK TABLES;
DROP TABLE tmp;

licensed under cc by-sa 3.0 with attribution.