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
Форумы портала PHP.SU :: Версия для печати :: сортировка перед группировкой mysql
Форумы портала PHP.SU » » Работа с СУБД » сортировка перед группировкой mysql

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

1. OrmaJever - 21 Января, 2015 - 14:08:51 - перейти к сообщению
Есть простая тестовая таблица
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 раз когда нужна сортировка перед группировкой.
2. Sail - 21 Января, 2015 - 14:25:22 - перейти к сообщению
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`
3. Мелкий - 21 Января, 2015 - 14:30:05 - перейти к сообщению
OrmaJever пишет:
Но там есть JOIN, и в нём mid не видно

Что сие значит?
4. OrmaJever - 21 Января, 2015 - 14:32:53 - перейти к сообщению
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 - без вложенных запросов, точнее без тех в которых нельзя сделать лимит
5. and_07 - 21 Января, 2015 - 14:44:17 - перейти к сообщению
а если как то так

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 поиграться еще можно
6. OrmaJever - 21 Января, 2015 - 14:45:14 - перейти к сообщению
and_07
CODE (htmlphp):
скопировать код в буфер обмена
  1. [Err] 1111 - Invalid use of group function
7. and_07 - 21 Января, 2015 - 14:48:37 - перейти к сообщению
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
8. OrmaJever - 21 Января, 2015 - 14:52:04 - перейти к сообщению
and_07 пишет:
SELECT max(t.id) mid, t.name
FROM test t

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

У меня есть рабочий запрос (в первом посте), но он слишком долго выполняется, мне нужно ему замена без вложенных запросов.
9. Мелкий - 21 Января, 2015 - 14:59:47 - перейти к сообщению
OrmaJever пишет:
без вложенных запросов, точнее без тех в которых нельзя сделать лимит

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

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

В случае наличия индекса по name вообще таблицу трогать не будет, чистый index scan.
Если этого мало - денормализуйте в требуемое место ссылку на нужный id и поддерживайте её актуальность.
10. and_07 - 21 Января, 2015 - 15:02:59 - перейти к сообщению
ну смотри тогда explain analyze
ищи что жрет время
11. OrmaJever - 21 Января, 2015 - 15:15:17 - перейти к сообщению
Спасибо ребята, всё таки намёк я уловил и в запросе с первого поста
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(!!!)
Огромное спасибо! Подмигивание

 

Powered by ExBB FM 1.0 RC1