Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: сортировка перед группировкой mysql

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
OrmaJever Модератор
Отправлено: 21 Января, 2015 - 14:08:51
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




Есть простая тестовая таблица
id name
CODE (htmlphp):
скопировать код в буфер обмена
  1. 1   Orma
  2. 2   Orma
  3. 3   OrmaJever
  4. 4   OrmaJever

Нужно взять группированные данные, но что бы из каждой группы брался последний id, а не первый. Вот запрос который делает то что нужно
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT t.id, t.name
  2. FROM (SELECT id, name FROM test ORDER BY id DESC) t
  3. GROUP BY t.name
  4. ORDER BY t.id DESC
  5. LIMIT 10

Но вложенный запрос возвращает всю таблицу и профайлер мне делает атата за это.
Был вариант делать так
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT max(t.id) mid, name
  2. FROM test
  3. GROUP BY name
  4. ORDER BY id DESC;

Но там есть JOIN, и в нём mid не видно, а если обьеденять просто по id то mid будет последний, а данные из соседней таблицы взяты по первому id из группы.
В общем нужен совет как лучше запрос написать. Это уже 3 раз когда нужна сортировка перед группировкой.


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Sail
Отправлено: 21 Января, 2015 - 14:25:22
Post Id



Участник


Покинул форум
Сообщений всего: 1131
Дата рег-ции: Февр. 2014  


Помог: 57 раз(а)




OrmaJever пишет:
Но там есть JOIN, и в нём mid не видно

Отчего-же не видно?
Если, например, таким образом:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT t1.`field1`, t2.`mid` FROM `tablename` t1
  2. JOIN (SELECT max(`id`) AS mid FROM `sometable` GROUP BY `name`) t2 ON t2.`mid` = t1.`id`
 
 Top
Мелкий Супермодератор
Отправлено: 21 Января, 2015 - 14:30:05
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




OrmaJever пишет:
Но там есть JOIN, и в нём mid не видно

Что сие значит?


-----
PostgreSQL DBA
 
 Top
OrmaJever Модератор
Отправлено: 21 Января, 2015 - 14:32:53
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




Sail пишет:
Отчего-же не видно?

mysql видимо так решила
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT max(t.id) mid, t.name
  2. FROM test t
  3. JOIN users u
  4.         ON u.id = mid
  5. GROUP BY name
  6. ORDER BY did DESC

CODE (htmlphp):
скопировать код в буфер обмена
  1. [Err] 1054 - Unknown column 'mid' in 'on clause'

Sail пишет:
Если, например, таким образом:

Правило №0 - без вложенных запросов, точнее без тех в которых нельзя сделать лимит


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
and_07
Отправлено: 21 Января, 2015 - 14:44:17
Post Id


Гость


Покинул форум
Сообщений всего: 91
Дата рег-ции: Сент. 2012  


Помог: 3 раз(а)




а если как то так

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT max(t.id) mid, t.name
  2. FROM test t
  3. JOIN users u
  4.         ON u.id = max(t.id)
  5. GROUP BY name
  6. ORDER BY did DESC


+ с having поиграться еще можно

(Отредактировано автором: 21 Января, 2015 - 14:46:17)

 
 Top
OrmaJever Модератор
Отправлено: 21 Января, 2015 - 14:45:14
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




and_07
CODE (htmlphp):
скопировать код в буфер обмена
  1. [Err] 1111 - Invalid use of group function


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
and_07
Отправлено: 21 Января, 2015 - 14:48:37
Post Id


Гость


Покинул форум
Сообщений всего: 91
Дата рег-ции: Сент. 2012  


Помог: 3 раз(а)




CODE (SQL):
скопировать код в буфер обмена
  1. SELECT * FROM (
  2.  
  3. SELECT max(t.id) mid, t.name
  4. FROM test t
  5. ) t
  6.  
  7. JOIN users u
  8.         ON u.id =t.mid
  9.  
  10. GROUP BY name
  11. ORDER BY did DESC
 
 Top
OrmaJever Модератор
Отправлено: 21 Января, 2015 - 14:52:04
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




and_07 пишет:
SELECT max(t.id) mid, t.name
FROM test t

этот запрос выбирает абсолютно всю таблицу, это очень не продуктивно, ещё раз
OrmaJever пишет:
Правило №0 - без вложенных запросов, точнее без тех в которых нельзя сделать лимит

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


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Мелкий Супермодератор
Отправлено: 21 Января, 2015 - 14:59:47
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




OrmaJever пишет:
без вложенных запросов, точнее без тех в которых нельзя сделать лимит

... указанная задача решения не имеет.

Нормально работают вложенные подзапросы.
Указанный выше
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT max(`id`) AS mid FROM `sometable` GROUP BY `name`

В случае наличия индекса по name вообще таблицу трогать не будет, чистый index scan.
Если этого мало - денормализуйте в требуемое место ссылку на нужный id и поддерживайте её актуальность.


-----
PostgreSQL DBA
 
 Top
and_07
Отправлено: 21 Января, 2015 - 15:02:59
Post Id


Гость


Покинул форум
Сообщений всего: 91
Дата рег-ции: Сент. 2012  


Помог: 3 раз(а)




ну смотри тогда explain analyze
ищи что жрет время
 
 Top
OrmaJever Модератор
Отправлено: 21 Января, 2015 - 15:15:17
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




Спасибо ребята, всё таки намёк я уловил и в запросе с первого поста
OrmaJever пишет:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT t.id, t.name
  2. FROM (SELECT id, name FROM test ORDER BY id DESC) t
  3. GROUP BY t.name
  4. ORDER BY t.id DESC
  5. LIMIT 10

изменил вложеный запрос на
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT max(id) id, name FROM test GROUP BY id LIMIT 10

и 610мс превратились в 14(!!!)
Огромное спасибо! Подмигивание


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Работа с СУБД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB