SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

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

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

Вы не зашли.

#1 19.02.2011 22:30:44

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

GROUP BY ORDER BY помогите составить запрос

Всем привет.
Может на этом форуме кто то помочь разобраться с выборкой и ранжированием значений?
Обращался на другой форум, смогли помочь только частично, надеюсь тут есть профессионалы, хорошо знающие MySQL.
Еть поля:

id | login | time
1 | log1 | 10
2 | log1 | 15
3 | log2 | 100
4 | log2 | 80
5 | log3 | 11
6 | log4 | 8

Нужно сгруппировать по столбцу login что бы сгруппировалось по максимальному time , вот так

id | login | time
3 | log2 | 100
2 | log1 | 15
5 | log3 | 11
6 | log4 | 8

Подсказали мне вот такой код

SELECT `login`, max(`time`) AS `time` FROM `tabl` GROUP BY `login` ORDER BY 2 DESC

Он работает так как мне и было нужно, но есть одно НО
При этом коде выводится только 2 поля login и time, остальные поля не могу выбрать.
Подскажите как правильно создать запрос, что бы работал аналогично приведенному выше,
но что бы можно было делать выборку всех полей. (их больше чем в примере).
Надеюсь на ваш проффесионализм.


Комментарий модератора:
Обзор способов решения данной задачи разобран в статье Группировка в MySQL

Неактивен

 

#2 20.02.2011 12:36:43

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: GROUP BY ORDER BY помогите составить запрос

Группировка подразумевает "сжатие" по некоторому признаку (максимальное значение, минимальное значение, среднее, сумма, общее количество), и если Вы делаете запрос с группировкой (как в примере запроса, который Вам привели), то те поля, которые Вы выбираете - на них придётся подействовать агрегирующей функцией. Или Вы хотите получить id-шники записей, чтобы потом уже по ним выбрать все остальное?


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#3 20.02.2011 13:02:18

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

Re: GROUP BY ORDER BY помогите составить запрос

Я хочу получить вывод данных как показано в примере (таблица №2)

Неактивен

 

#4 20.02.2011 13:06:59

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: GROUP BY ORDER BY помогите составить запрос

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

Занесите в массив (на той технологии программирования, на который Вы пишете) результат выборки: select distinct login from `tabl`;

Пройдите по всем элементам этого массива с запросом:

SELECT `id`,`login`,time FROM `tabl where login='ОЧЕРЕДНОЙ_ЭЛЕМЕНТ_МАССИВА_ЛОГИНОВ' order by time desc limit 1;

Господа Архаты - если можно изящнее (без пользовательских переменных) - прошу в студию.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#5 20.02.2011 13:46:27

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

Re: GROUP BY ORDER BY помогите составить запрос

deadka написал:

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

Занесите в массив (на той технологии программирования, на который Вы пишете) результат выборки: select distinct login from `tabl`;

Пройдите по всем элементам этого массива с запросом:

SELECT `id`,`login`,time FROM `tabl where login='ОЧЕРЕДНОЙ_ЭЛЕМЕНТ_МАССИВА_ЛОГИНОВ' order by time desc limit 1;

Господа Архаты - если можно изящнее (без пользовательских переменных) - прошу в студию.

Не вариант. В таблице более 80,000 строк

Неактивен

 

#6 20.02.2011 14:10:42

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: GROUP BY ORDER BY помогите составить запрос

Подобный вопрос обсуждался. Решается через подзапросы. Запрос ниже будет работать, если (login,time) будет уникальной парой, то есть для каждого юзера максимальное время единственно.

SELECT t2.* FROM (SELECT `login`, max(`time`) AS `time` FROM `tbl` GROUP BY `login`) t1 JOIN tbl t2 USING(login,time) ORDER BY t1.time DESC;

Неактивен

 

#7 20.02.2011 15:00:37

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

Re: GROUP BY ORDER BY помогите составить запрос

rgbeast написал:

Подобный вопрос обсуждался. Решается через подзапросы. Запрос ниже будет работать, если (login,time) будет уникальной парой, то есть для каждого юзера максимальное время единственно.

SELECT t2.* FROM (SELECT `login`, max(`time`) AS `time` FROM `tbl` GROUP BY `login`) t1 JOIN tbl t2 USING(login,time) ORDER BY t1.time DESC;

К сожалению ваш вариант работает не так как мне нужно, сбивается сортировка , тоесть группирует не по максимальному time (пара login,time уникальна)

P.S Возможно я не совсем доступно обьяснил что жду от запроса, обьясню по другому.

Маша купила вещь на сумму  100 руб
Маша купила вещь на сумму  20 руб
Маша купила вещь на сумму  110 руб

Паша купил вещь на сумму 30 руб
Паша купил вещь на сумму 50 руб

Даша купила вещь на сумму 10 руб
Даша купила вещь на сумму 800 руб
Даша купила вещь на сумму 40 руб
Даша купила вещь на сумму 30 руб

Нужно сгруппировать покупки по имени и по максимальной сумме, вот так

Маша 110 руб
Паша 50 руб
Даша 800 руб

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

Даша 800 руб
Маша 110 руб
Паша 50 руб

Вот такой конечный вывод меня интересует.

Неактивен

 

#8 20.02.2011 15:40:47

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: GROUP BY ORDER BY помогите составить запрос

А какой вывод получается от запроса, который я привел? Объясняйте лучше на конкретном примере, а не на упрощенном, для которого работает и метод в первом посте.

Неактивен

 

#9 20.02.2011 16:25:56

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

Re: GROUP BY ORDER BY помогите составить запрос

rgbeast написал:

А какой вывод получается от запроса, который я привел? Объясняйте лучше на конкретном примере, а не на упрощенном, для которого работает и метод в первом посте.

Сорри, щас снова начал тестировать ваш запрос и о чудо, работает правильно, спасибо большое за помощь.
Единственный минус, это генерация страницы.
По всему сайту генерация 0.02 - 0.08 А на той странице где стоит выборка с этим запросом, генерация 0.8
Скажите пожалуйста нельзя как нибудь оптимизировать запрос, что бы генерация была поменьше?
P.S В таблице бывает от 40,000 до 100,000 строк

Неактивен

 

#10 20.02.2011 16:42:10

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: GROUP BY ORDER BY помогите составить запрос

Создайте составной индекс KEY(login,time), если еще не создан

Неактивен

 

#11 20.02.2011 18:08:36

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

Re: GROUP BY ORDER BY помогите составить запрос

Спаибо. При установке индексов для time и login, генерация уменьшена до 0.1

Неактивен

 

#12 20.02.2011 18:16:20

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: GROUP BY ORDER BY помогите составить запрос

ZloiKombat написал:

Спаибо. При установке индексов для time и login, генерация уменьшена до 0.1

Вы сделали два отдельных индекса? Это тоже полезно, но эффект будет лучше, если сделать один составной индекс, включающий две колонки.

Неактивен

 

#13 20.02.2011 19:38:47

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

Re: GROUP BY ORDER BY помогите составить запрос

rgbeast написал:

ZloiKombat написал:

Спаибо. При установке индексов для time и login, генерация уменьшена до 0.1

Вы сделали два отдельных индекса? Это тоже полезно, но эффект будет лучше, если сделать один составной индекс, включающий две колонки.

Если не трудно, подскажите пожалуйста как сделать составной индекс? (пользуюсь phpmyadmin)

Неактивен

 

#14 20.02.2011 19:47:03

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: GROUP BY ORDER BY помогите составить запрос

1. Удалите одиночные индексы
2. Выполните запрос
ALTER TABLE `tbl` ADD KEY(`login`,`time`);

Неактивен

 

#15 20.02.2011 19:47:10

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

Re: GROUP BY ORDER BY помогите составить запрос

Кажется разобрался как сделать составной индекс, генерация уменьшена до 0.05 спасибо большое.
Все же с кодом запроса обнаружились недостатки.Некоторые строки на выводе дублируются(((
То есть вывод типа такого

id | login | time
3 | log2 | 100
2 | log1 | 15
2 | log1 | 15
5 | log3 | 11
6 | log4 | 8

Неактивен

 

#16 20.02.2011 20:01:21

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: GROUP BY ORDER BY помогите составить запрос

Есть такой недостаток из-за неуникальности времени. Есть несколько способов бороться:
1. записывать time более точно, чтобы оно было уникальным
2. фильтровать в PHP при выводе (это лучшее по производительности решение
3. Средствами MySQL это усложнит запрос

SELECT t2.* FROM (SELECT `login`, max(`time`) AS `time` FROM `tbl` GROUP BY `login`) t1 JOIN tbl t2 USING(login,time) GROUP BY t2.login,t2.time ORDER BY t1.time DESC;

Неактивен

 

#17 20.02.2011 21:00:45

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

Re: GROUP BY ORDER BY помогите составить запрос

Я сделал индекс по связки login+time уникальным. Это исключит неуникальность записей? И насколько это действенно по производительности?

Неактивен

 

#18 20.02.2011 21:02:34

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: GROUP BY ORDER BY помогите составить запрос

Это исключит неуникальность записей и для производительности это ОК. Но теперь в таблице не может быть двух записей с повторяющейся парой login,time - при попытке вставить такую пару будет ошибка. Это не повредит работе других скриптов?

Неактивен

 

#19 20.02.2011 21:17:43

ZloiKombat
Участник
Зарегистрирован: 19.02.2011
Сообщений: 18

Re: GROUP BY ORDER BY помогите составить запрос

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

mysql_num_rows не подойдет, так как полученное число подсчета нужно бут записать в сам запрос типа LIMIT $start,$total

SELECT t2.* FROM (SELECT `login`, max(`time`) AS `time` FROM `tbl` GROUP BY `login`) t1 JOIN tbl t2 USING(login,time) ORDER BY t1.time DESC LIMIT $start,$total;

Неактивен

 

#20 20.02.2011 21:30:50

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: GROUP BY ORDER BY помогите составить запрос

Если отдельным запросом, то можно

SELECT COUNT(DISTINCT login) c FROM tbl;

Неактивен

 

#21 21.02.2011 08:45:26

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: GROUP BY ORDER BY помогите составить запрос

rgbeast, скажи пожалуйста, а если вернуться к самой изначальной постановке вопроса - то

ZloiKombat написал:

Нужно сгруппировать по столбцу login что бы сгруппировалось по максимальному time , вот так

id | login | time
3 | log2 | 100
2 | log1 | 15
5 | log3 | 11
6 | log4 | 8

(если никакие другие поля кроме login, id и time не выбираются), то
можно ли было бы ограничиться запросом


 SELECT `id` , `login` , max( `time` ) AS `time` FROM `tabl` GROUP BY `login` ORDER BY 3 DESC;
 
?


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#22 21.02.2011 10:13:10

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: GROUP BY ORDER BY помогите составить запрос

Не совсем. id и time не будут взаимосвязаны. Если id убрать, то ок.

Неактивен

 

#23 11.08.2011 12:13:37

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: GROUP BY ORDER BY помогите составить запрос

На самом деле здесь можно вывернуться через пользовательские переменные, вот так:

set @i=0,@n=1,@l=''; select t.* from ( select * from tabl order by login, time desc) t where if (@l=login, @i:=@i+1,(@i:=0) or (@l:=login) or 1) and @i<@n;


or 1 после @l:=login нужно из-за того, что результат операции присваивания в переменную @l строки почему-то равен нулю smile.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

Board footer

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