Помогите составить запрос mysql

FS
На сайте с 20.04.2008
Offline
18
1055

Здравствуйте!

Имеется таблица с текстом, датой, группой.

Мне нужно упорядочить по дате (в порядке убывания), при этом должно браться по 3 материала с каждой группы. Как это сделать в виде запроса?

P
На сайте с 02.06.2009
Offline
14
#1

Очень объемное описание...

На такое описание можно и ответить: взять и сделать в виде запроса. Структуру таблицы хотя бы "в студию" выдали...

M
На сайте с 10.06.2009
Offline
16
#2

mysql_query("SELECT text, date, group FROM table ORDER BY date DESC");

остальное парсишь PHP

text, date, group - названия полей таблицы

table - имя таблицы

ICQ 386414065 skype webmtnt email request@webmutant.ru
Коля Дубр
На сайте с 02.03.2005
Offline
153
#3

Да, бывает такая задачка :) Кажется, "прямого" решения нету.

Mtnt, да, как-то так. Либо, если данных зело дофига, а групп не очень -

SELECT DISTINCT(`group`) FROM table

и дальше по результату - циклом:

SELECT * FROM tbl WHERE `group`=  $group ORDER BY `date` LIMIT 3

На group должен быть индекс. Но это - на крайний случай. В идеале - пересмотреть задачу :)

Разрабатываю общую шину (http://habrahabr.ru/company/floxim/blog/268467/) помаленьку. ...а еще у меня есть бложек (http://www.blogovo.ru/).
edogs software
На сайте с 15.12.2005
Offline
775
#4
FL|\/|@ster:
Здравствуйте!
Имеется таблица с текстом, датой, группой.
Мне нужно упорядочить по дате (в порядке убывания), при этом должно браться по 3 материала с каждой группы. Как это сделать в виде запроса?

Нормальных решений чисто мускульных как минимум 2 (пхп-шные очевидны).

Подразумеваем что ID уникальный есть и по сортировке соответствует датам, для простоты.

1) Нечто вроде следующего (для 2 материалов, для 3 просто продолжаем)


select * from _tmp as a
left join _tmp as b on a.id<b.id and a.grp=b.grp
left join _tmp as с on b.id<c.id and b.grp=c.grp
where c.id is null group by a.grp order by a.dta

смысл запроса в вытягивании 3 строк в одну строку, при кол-ве нужных записей до 16 штук обычно летает:)

2) Нечто вроде следующего


SELECT *,
group_concat( concat_ws('~',txt,dta) order by dta asc separator '=' )
FROM `_tmp` WHERE 1
group by grp
order by dta

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

set session group_concat_max_len=1024; #1024- кол-во символов в выборке

Конечно должны быть индексы на id и grp.

Первый вариант в случае отсутствия id тоже решаем, нужно просто использовать вместо id дату, а случаи совпадения дат отсеивать с помощью проверки на разность в других полях (но умнее конечно id ввести).

P.S.: А вообще в таких случаях проще всего слегка "кэшировать" это дело. То есть при добавлении записи, смотреть ее группу, и 3 последние записи этой же группы апдейтить флагом "last3" (в отдельном поле). Тогда Вы в разы облегчите себе дальнейшие выборки, потому что оба вышеозначенных варианта, несмотря на индексы - все-таки сложнее чем прямая выборка. А вариант на php вообще ужасен с точки зрения скорости.

Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход. Продаем lenovo legion в спб, дешевле магазинов, новые, запечатанные. Есть разные. skype: edogssoft
[Удален]
#5

я бы посоветовал такие вещи помечать галочкой при обновлении таблицы, ожно через триггер. гавлочка - типа поле "new". а все эти мудако приемы про циклы и конкаты страшные - при большой бд .... :))

FS
На сайте с 20.04.2008
Offline
18
#6
Коля Дубр:
Да, бывает такая задачка :) Кажется, "прямого" решения нету.

Mtnt, да, как-то так. Либо, если данных зело дофига, а групп не очень -
SELECT DISTINCT(`group`) FROM table

и дальше по результату - циклом:
SELECT * FROM tbl WHERE `group`=  $group ORDER BY `date` LIMIT 3

На group должен быть индекс. Но это - на крайний случай. В идеале - пересмотреть задачу :)

Было в мыслях такое. Думал, что можно в один запрос, а оказалось не так уже просто. :)

Думаю его использовать.

edogs, спасибо, что все так расписали! Запросы выглядят страшно :) (планирую крупную базу)

1 запрос жалуется на Unknown column 'c.id' in 'where clause'

2 запрос работает, но выдает по 1 статье с каждой группы

Всем спасибо за советы!

Коля Дубр
На сайте с 02.03.2005
Offline
153
#7
FL|/|@ster:
1 запрос жалуется на Unknown column 'c.id' in 'where clause'

left join _tmp as с on b.id<c.id and b.grp=c.grp

Тут вместо латинской "си" влезла русская "эс" :)

На 19К строк при 17 группах и 3х результатах из группы у меня выполняется за 0.7 сек., индексы на месте, EXPLAIN не смотрел.

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

Ну да, нормальный вариант. Если, конечно, результат не фильтруется по правам пользователя или еще как-то.

[Удален]
#8

Коля Дубр, если не фильтруется то да, а если филтруется, то мну кажетсо что есть подобное решение, но чуток модифицированное ... )))

edogs software
На сайте с 15.12.2005
Offline
775
#9
Коля Дубр:

На 19К строк при 17 группах и 3х результатах из группы у меня выполняется за 0.7 сек., индексы на месте, EXPLAIN не смотрел.

Долговато если честно, при условии что сервер нормальный. У нас вариант с лефт-джоинами на больших таблицах быстрее всего получается среди всех альтернатив известных, даже на 100к строк и 16 результатах в 0.1 помещается, поэтому деревья подобным образом выбираем. А индекс у Вас составной на grp, id ?

FL|\/|@ster:
2 запрос работает, но выдает по 1 статье с каждой группы

Скорее всего или что-то не так написали, или у Вас переменная group_concat_max_len слишком маленькое значение имеет. Там как бы в принципе не может по 1 статье выдавать, ибо mysql.org/group_concat должен все выбирать в группе.

Коля Дубр
На сайте с 02.03.2005
Offline
153
#10
edogs:
А индекс у Вас составной на grp, id ?

А какой смысл в составном индексе, включающем primary? :)

Проверял на ноуте.

bearman:
а если филтруется, то мну кажетсо что есть подобное решение, но чуток модифицированное ... )))

Если фильтруется, модифицированное решение будет приблизительно равно кэшированию выдачи с параметром фильтрации в ключе :) Или нет?

FL|/|@ster, я бы все-таки делал на PHP. SQL-решение - полезно для тренировки мозга (респект edogs, кстати), но в любом случае требует доп. обработки в коде. Не факт, что получится выигрыш по производительности, зато факт, что усложняется логика. Не стоит заниматься преждевременной оптимизацией.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий