Задавайте вопросы, мы ответим
Вы не зашли.
Всем привет.
Может на этом форуме кто то помочь разобраться с выборкой и ранжированием значений?
Обращался на другой форум, смогли помочь только частично, надеюсь тут есть профессионалы, хорошо знающие 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
Неактивен
Группировка подразумевает "сжатие" по некоторому признаку (максимальное значение, минимальное значение, среднее, сумма, общее количество), и если Вы делаете запрос с группировкой (как в примере запроса, который Вам привели), то те поля, которые Вы выбираете - на них придётся подействовать агрегирующей функцией. Или Вы хотите получить id-шники записей, чтобы потом уже по ним выбрать все остальное?
Неактивен
Я хочу получить вывод данных как показано в примере (таблица №2)
Неактивен
В таком случае попробуйте серией запросов (думаю, что можно более изящно, но сходу не назову как):
Занесите в массив (на той технологии программирования, на который Вы пишете) результат выборки: select distinct login from `tabl`;
Пройдите по всем элементам этого массива с запросом:
SELECT `id`,`login`,time FROM `tabl where login='ОЧЕРЕДНОЙ_ЭЛЕМЕНТ_МАССИВА_ЛОГИНОВ' order by time desc limit 1;
Господа Архаты - если можно изящнее (без пользовательских переменных) - прошу в студию.
Неактивен
deadka написал:
В таком случае попробуйте серией запросов (думаю, что можно более изящно, но сходу не назову как):
Занесите в массив (на той технологии программирования, на который Вы пишете) результат выборки: select distinct login from `tabl`;
Пройдите по всем элементам этого массива с запросом:
SELECT `id`,`login`,time FROM `tabl where login='ОЧЕРЕДНОЙ_ЭЛЕМЕНТ_МАССИВА_ЛОГИНОВ' order by time desc limit 1;
Господа Архаты - если можно изящнее (без пользовательских переменных) - прошу в студию.
Не вариант. В таблице более 80,000 строк
Неактивен
Подобный вопрос обсуждался. Решается через подзапросы. Запрос ниже будет работать, если (login,time) будет уникальной парой, то есть для каждого юзера максимальное время единственно.
Неактивен
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 руб
Вот такой конечный вывод меня интересует.
Неактивен
А какой вывод получается от запроса, который я привел? Объясняйте лучше на конкретном примере, а не на упрощенном, для которого работает и метод в первом посте.
Неактивен
rgbeast написал:
А какой вывод получается от запроса, который я привел? Объясняйте лучше на конкретном примере, а не на упрощенном, для которого работает и метод в первом посте.
Сорри, щас снова начал тестировать ваш запрос и о чудо, работает правильно, спасибо большое за помощь.
Единственный минус, это генерация страницы.
По всему сайту генерация 0.02 - 0.08 А на той странице где стоит выборка с этим запросом, генерация 0.8
Скажите пожалуйста нельзя как нибудь оптимизировать запрос, что бы генерация была поменьше?
P.S В таблице бывает от 40,000 до 100,000 строк
Неактивен
Создайте составной индекс KEY(login,time), если еще не создан
Неактивен
Спаибо. При установке индексов для time и login, генерация уменьшена до 0.1
Неактивен
ZloiKombat написал:
Спаибо. При установке индексов для time и login, генерация уменьшена до 0.1
Вы сделали два отдельных индекса? Это тоже полезно, но эффект будет лучше, если сделать один составной индекс, включающий две колонки.
Неактивен
rgbeast написал:
ZloiKombat написал:
Спаибо. При установке индексов для time и login, генерация уменьшена до 0.1
Вы сделали два отдельных индекса? Это тоже полезно, но эффект будет лучше, если сделать один составной индекс, включающий две колонки.
Если не трудно, подскажите пожалуйста как сделать составной индекс? (пользуюсь phpmyadmin)
Неактивен
1. Удалите одиночные индексы
2. Выполните запрос
ALTER TABLE `tbl` ADD KEY(`login`,`time`);
Неактивен
Кажется разобрался как сделать составной индекс, генерация уменьшена до 0.05 спасибо большое.
Все же с кодом запроса обнаружились недостатки.Некоторые строки на выводе дублируются(((
То есть вывод типа такого
id | login | time
3 | log2 | 100
2 | log1 | 15
2 | log1 | 15
5 | log3 | 11
6 | log4 | 8
Неактивен
Есть такой недостаток из-за неуникальности времени. Есть несколько способов бороться:
1. записывать time более точно, чтобы оно было уникальным
2. фильтровать в PHP при выводе (это лучшее по производительности решение
3. Средствами MySQL это усложнит запрос
Неактивен
Я сделал индекс по связки login+time уникальным. Это исключит неуникальность записей? И насколько это действенно по производительности?
Неактивен
Это исключит неуникальность записей и для производительности это ОК. Но теперь в таблице не может быть двух записей с повторяющейся парой login,time - при попытке вставить такую пару будет ошибка. Это не повредит работе других скриптов?
Неактивен
Нет, не принципиально существование дубликатов связки, достаточно всех в единственном экземпляре.
По ходу пьесы спрошу у вас еще такой момент.
Скажите пожалуйста как теперь подсчитать колличество групп сгруппированых по 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;
Неактивен
Если отдельным запросом, то можно
Неактивен
rgbeast, скажи пожалуйста, а если вернуться к самой изначальной постановке вопроса - то
ZloiKombat написал:
Нужно сгруппировать по столбцу login что бы сгруппировалось по максимальному time , вот так
id | login | time
3 | log2 | 100
2 | log1 | 15
5 | log3 | 11
6 | log4 | 8
(если никакие другие поля кроме login, id и time не выбираются), то
можно ли было бы ограничиться запросом
Неактивен
Не совсем. id и time не будут взаимосвязаны. Если id убрать, то ок.
Неактивен
На самом деле здесь можно вывернуться через пользовательские переменные, вот так:
Неактивен