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 :: Сложная сортировка

 PHP.SU

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


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

> Описание: Помогите понять
Anguis
Отправлено: 09 Февраля, 2013 - 10:42:57
Post Id



Частый гость


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


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




Здравствуйте! Помогите разобраться с сортировкой по связанным таблицам.
Пример:
Таблица users
+----+----------------+----------------+-------+
| id | name | sername | other |
+----+----------------+----------------+-------+
| 1 | алексей | сидоров | |
| 2 | андрей | давыдов | |
| 3 | Семен | Пошты | |
| 4 | Дамир | Исулаев | |
+----+----------------+----------------+-------+

Таблица meta
mysql> SELECT * FROM meta;
+----+---------+------+-------+
| id | user_id | rate | other |
+----+---------+------+-------+
| 1 | 4 | 10 | |
| 2 | 1 | 3 | |
| 3 | 3 | 44 | |
| 4 | 2 | 12 | |
+----+---------+------+-------+

Необходимо делать выборку всего из users, отсортированного по meta.rate, при этом из meta кроме принципа сортировки ни чего не получаем. Результат должен быть следующим:
3 Семен Пошты //rate = 44
2 андрей давыдов //rate = 12
4 Дамир Исулаев //rate = 10
1 алексей сидоров //rate = 3
 
 Top
DeepVarvar Супермодератор
Отправлено: 09 Февраля, 2013 - 10:54:12
Post Id



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


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




CODE (SQL):
скопировать код в буфер обмена
  1. SELECT u.id, u.name, u.sername, m.rate
  2.   FROM users u
  3.   JOIN meta m ON m.user_id = u.id
  4.   ORDER BY m.rate DESC


Почитайте чтобы понять: http://forum.php.su/topic.php?forum=33&topic=771
 
 Top
Anguis
Отправлено: 09 Февраля, 2013 - 12:18:56
Post Id



Частый гость


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


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




Благодарю! Прочитал и по ссылке и так про Join-ы, но не совсем понял.
Вот сложный пример из реальной жизни с которым трахаюсь уже второй день. Есть таблица с данными небольшого форума (школьный сайт, разрабатывался школьниками). Таблица не нормализована, и записи с форумом, темами и постами хранятся в ней одной.
Есть запрос
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT Forum.*, Users.json user
  3. FROM Forum, Users
  4. WHERE Forum.type='topic' AND Forum.forum_id = $id AND Users.id = Forum.user_id
  5. LIMIT 30;
  6.  

Который выводит топики в конкретном форуме с информацией и о создателе (Users.json). Моя задача стоит в том, что-бы этот вывод отсортировать по последнему добавленному сообщению, при том что эти сообщения добавляются в ту-же самую таблицу.
По тому что я понял, я пробую делать так:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT Forum.*, Users.json user
  3. FROM Forum JOIN Users ON Users.id = Forum.user_id JOIN Forum f ON f.topic_id=Forum.id
  4. WHERE Forum.type='topic' AND Forum.forum_id = 1 AND f.type = 'post'
  5. ORDER BY f.id DESC
  6.  

Сортирует как надо, только вот беда, в результат попадают повторы, ровно столько, сколько найдено f.type = 'post'. Если добавляю GROUP BY вот так:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT Forum.*, Users.json user
  3. FROM Forum JOIN Users ON Users.id = Forum.user_id JOIN Forum f ON f.topic_id=Forum.id
  4. WHERE Forum.type='topic' AND Forum.forum_id = 1 AND f.type = 'post'
  5. GROUP BY f.topic_id
  6. ORDER BY f.id DESC
  7.  

То порядок сортировки меняется и становится неверным. В случае с DISTINCT то-же самое что и в GROUP BY

(Отредактировано автором: 09 Февраля, 2013 - 12:19:49)

 
 Top
imya
Отправлено: 09 Февраля, 2013 - 14:26:41
Post Id



Участник


Покинул форум
Сообщений всего: 1472
Дата рег-ции: Сент. 2012  
Откуда: Запорожье, Украина


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




Делайте либо GROUP BY || DISTINICT. Вместе их лучше не смешивать.

(Отредактировано автором: 09 Февраля, 2013 - 14:27:43)



-----
PHP:
скопировать код в буфер обмена
  1. do {box != cat;} while (cat != box);


Когда нормальный человек, уезжая из дома одевает на жену пояс верности, веб-дизайнер ставит на нее счетчик...
 
My status
 Top
DeepVarvar Супермодератор
Отправлено: 09 Февраля, 2013 - 14:39:35
Post Id



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


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




Anguis Я не понял за что нужно зацепиться в выборке и сортировке.. Опишите так же корректно как в первом посте, где немедленно и получили ответ.
 
 Top
Anguis
Отправлено: 09 Февраля, 2013 - 14:40:32
Post Id



Частый гость


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


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




Говорю-же результат сортировки меняется!
Вот создал упрошенную версию таблицы для экспериментов.
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. mysql> SELECT * FROM test.Test;
  3. +----+----------+----------+-------+
  4. | id | forum_id | topic_id | type  |
  5. +----+----------+----------+-------+
  6. |  1 |        1 |        0 | forum |
  7. |  2 |        1 |        2 | topic |
  8. |  3 |        1 |        3 | topic |
  9. |  4 |        1 |        4 | topic |
  10. |  5 |        1 |        2 | post  |
  11. |  6 |        1 |        4 | post  |
  12. |  7 |        1 |        3 | post  |
  13. +----+----------+----------+-------+
  14. 7 rows IN SET (0.00 sec)
  15.  


Вот такой запрос:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. mysql> SELECT f . *, m.id sid   FROM test.Test f  JOIN test.Test m ON f.id = m.topic_id  WHERE f.forum_id =1  ORDER BY m.id DESC;
  3. +----+----------+----------+-------+-----+
  4. | id | forum_id | topic_id | type  | sid |
  5. +----+----------+----------+-------+-----+
  6. |  3 |        1 |        3 | topic |   7 |
  7. |  4 |        1 |        4 | topic |   6 |
  8. |  2 |        1 |        2 | topic |   5 |
  9. |  4 |        1 |        4 | topic |   4 |
  10. |  3 |        1 |        3 | topic |   3 |
  11. |  2 |        1 |        2 | topic |   2 |
  12. +----+----------+----------+-------+-----+
  13. 6 rows IN SET (0.00 sec)
  14.  

То, что нам нужно, только с повторами. Надо от них избавится:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. mysql> SELECT f . *, m.id sid   FROM test.Test f  JOIN test.Test m ON f.id = m.topic_id  WHERE f.forum_id =1 GROUP BY f.topic_id  ORDER BY m.id DESC;
  3. +----+----------+----------+-------+-----+
  4. | id | forum_id | topic_id | type  | sid |
  5. +----+----------+----------+-------+-----+
  6. |  4 |        1 |        4 | topic |   4 |
  7. |  3 |        1 |        3 | topic |   3 |
  8. |  2 |        1 |        2 | topic |   2 |
  9. +----+----------+----------+-------+-----+
  10. 3 rows IN SET (0.00 sec)
  11.  

При добавлении GROUP BY Сначала выполняется групировка, а потом уже сортировка сгруппированых значений - не верный результат
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. mysql> SELECT DISTINCT f . *   FROM test.Test f  JOIN test.Test m ON f.id = m.topic_id  WHERE f.forum_id =1  ORDER BY m.id DESC;
  3. +----+----------+----------+-------+
  4. | id | forum_id | topic_id | type  |
  5. +----+----------+----------+-------+
  6. |  4 |        1 |        4 | topic |
  7. |  3 |        1 |        3 | topic |
  8. |  2 |        1 |        2 | topic |
  9. +----+----------+----------+-------+
  10. 3 rows IN SET (0.00 sec)
  11.  

DISTINCT меняет сортировку вообще неведомым образом.

А результат должен быть следующим:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. +----+----------+----------+-------+-----+
  3. | id | forum_id | topic_id | type  | sid |
  4. +----+----------+----------+-------+-----+
  5. |  3 |        1 |        3 | topic |   7 |
  6. |  4 |        1 |        4 | topic |   6 |
  7. |  2 |        1 |        2 | topic |   5 |
  8. +----+----------+----------+-------+-----+
  9.  

(Добавление)
т.е. нужно отсортировать вывод топиков по последнему добавленному в него посту. Так как все добавляется с A_I то и сортируем мы по id. Последний добавленный пост имеет самый большой айди и по убыванию..
 
 Top
DeepVarvar Супермодератор
Отправлено: 09 Февраля, 2013 - 14:44:46
Post Id



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


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




DeepVarvar пишет:
Опишите так же корректно как в первом посте

Я не понял что у вас там дублируется
(Добавление)
???
 
 Top
Anguis
Отправлено: 09 Февраля, 2013 - 14:51:36
Post Id



Частый гость


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


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




Не получилось Недовольство, огорчение
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT f . *, m.id sid   FROM test.Test f  JOIN test.Test m ON f.id = m.topic_id  WHERE f.forum_id =1 GROUP BY f.id  ORDER BY m.id DESC;
  3. +----+----------+----------+-------+-----+
  4. | id | forum_id | topic_id | type  | sid |
  5. +----+----------+----------+-------+-----+
  6. |  4 |        1 |        4 | topic |   4 |
  7. |  3 |        1 |        3 | topic |   3 |
  8. |  2 |        1 |        2 | topic |   2 |
  9. +----+----------+----------+-------+-----+
  10. 3 rows IN SET (0.00 sec)
  11.  
 
 Top
DeepVarvar Супермодератор
Отправлено: 09 Февраля, 2013 - 14:53:24
Post Id



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


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




Anguis пишет:
Не получилось
Ну и что мы теперь гадать будем на каждом поле? Вы так и не сказали по какому полю нужна группировка и по каким условиям. Может это пост-группировка, тогда дело уже за HAVING.
 
 Top
Anguis
Отправлено: 09 Февраля, 2013 - 15:01:29
Post Id



Частый гость


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


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




Прошу прощения что невнятно изъясняюсь. Задача - вывести все топики (type='topic') в порядке последнего добавленного в него сообщения (стандартная фича на всех форумах)
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. mysql> SELECT * FROM test.Test;
  3. +---+----------+----------+-------+
  4. | id | forum_id | topic_id | type  |
  5. +----+----------+----------+-------+
  6. |  1 |        1 |        0 | forum |
  7. |  2 |        1 |        2 | topic |
  8. |  3 |        1 |        3 | topic |
  9. |  4 |        1 |        4 | topic |
  10. |  5 |        1 |        2 | post  |
  11. |  6 |        1 |        4 | post  |
  12. |  7 |        1 |        3 | post  |
  13. +----+----------+----------+-------+
  14. 7 rows IN SET (0.00 sec)

Как видно из таблицы топиков у нас всего три. Вот этот запрос верно сортирует, но добавляет дубликаты строк (по всем найденным id), вот нужен такой-же запрос только, что-бы в результате было не шесть строк, а три, по количеству топиков.
CODE (SQL):
скопировать код в буфер обмена
  1. mysql> SELECT f . *, m.id sid   FROM test.Test f  JOIN test.Test m ON f.id = m.topic_id  WHERE f.forum_id =1  ORDER BY m.id DESC;
  2. +----+----------+----------+-------+-----+
  3. | id | forum_id | topic_id | type  | sid |
  4. +----+----------+----------+-------+-----+
  5. |  3 |        1 |        3 | topic |   7 |
  6. |  4 |        1 |        4 | topic |   6 |
  7. |  2 |        1 |        2 | topic |   5 |
  8. |  4 |        1 |        4 | topic |   4 |
  9. |  3 |        1 |        3 | topic |   3 |
  10. |  2 |        1 |        2 | topic |   2 |
  11. +----+----------+----------+-------+-----+
  12. 6 rows IN SET (0.00 sec)

(Добавление)
Да, HAVING по-моему то, что нужно...
 
 Top
EuGen Администратор
Отправлено: 09 Февраля, 2013 - 15:09:06
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


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




SELECT DISTINCT ?


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Anguis
Отправлено: 09 Февраля, 2013 - 15:12:31
Post Id



Частый гость


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


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




EuGen пишет:
SELECT DISTINCT ?

Нет, меняет сортировку. Выше приводил пример.
 
 Top
EuGen Администратор
Отправлено: 09 Февраля, 2013 - 15:37:28
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


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




DISTINCT-поле указываете? Если нет, то не удивительно.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Anguis
Отправлено: 09 Февраля, 2013 - 17:18:54
Post Id



Частый гость


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


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




Указывал и id и topic_id, я уже все поперепробовал... Может вы подскажите?
 
 Top
Anguis
Отправлено: 09 Февраля, 2013 - 21:30:40
Post Id



Частый гость


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


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




ААААА!!!! Я ТАКИ ПОБЕДИЛ!!
Иногда ответ бывает очень близко, хоть и не очевиден на первый взгляд!
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT t.id sid, t1 . *
  3. FROM `Test` t, `Test` t1
  4. WHERE t.topic_id = t1.id
  5. AND t.type = 'post'
  6. GROUP BY t.topic_id
  7. ORDER BY t.id DESC
  8. LIMIT 0 , 30
  9.  

Таблица по которой выполняется сортировка должна быть приоритетной!!! СНАЧАЛА находим последние добавленные посты, потом уже из их записей берем инфу о топиках по topic_id, и дальше все что угодно!)) Благодарю всех кто отозвался. Mysql для меня труден в понимании, очень много нюансов. Зато теперь на всю жизнь запомню как mysql работает с приоритетами и как они порой бывают важны!)
(Добавление)
Однако желаемого результата сортировки я так и не добился.. Почему? Все из-за тех-же приоритетов, если быть точнее, порядка выполнения запроса. Все DISTINCT-ы и GROUP BY, а так-же WHERE и ON выполняются перед ORDER BY и упорядочивается результат уже сгруппированный и отсортированный всевозможными WHERE и DISTINCT. Можно и это обойти. Сделать так SELECT ... FROM (SELECT * FROM Forum ORDER BY id DESC) WHERE ... Однако тут уже встает вопрос производительности и оправданности такого метода. Ибо неизвестно сколько времени будет выполняться такой запрос на большой таблице в несколько тысяч строк...
Ни разу еще не сталкивался с таким ограничениями в MYSQL. Теперь понимаю, отчего некоторые программисты его хают.
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« SQL и Архитектура БД »


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



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

 
Powered by ExBB FM 1.0 RC1. InvisionExBB