Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Сложный запрос для форума с группировкой
 
 автор: Temnovit   (10.05.2007 в 11:36)   письмо автору
 
 

Долго мучаюсь над одним запросом - никак не могу сообразить.
Есть две таблицы

threads
id
name
description
author

messages
id
text
thread_id
author
add_date

В запросе нужно получить все записи из таблицы threads (тоесть список всех тем) и плюс к ним о каждой теме, колличество сообщений (COUNT(messages.id)), дату последнего сообщения (add_date) и автора последнего сообщения (с самым большим add_date).

В несколько запросов это без проблем, а вот как одним сделать... Подскажите пожалуйста.

   
 
 автор: Trianon   (10.05.2007 в 14:10)   письмо автору
 
   для: Temnovit   (10.05.2007 в 11:36)
 

примерно так.

SELECT threads.*, alls.cnt, alls.ldate, last.author AS lauthor
FROM threads
LEFT JOIN
  (SELECT COUNT(id) AS cnt, MAX(add_date) AS ldate,  thread_id
   FROM messages
    GROUP BY thread_id)
  AS alls ON threads.id = alls.thread_id
  LEFT JOIN messages AS last ON alls.ldate = messages.add_date
ORDER BY ldate DESC, cnt DESC

   
 
 автор: Temnovit   (11.05.2007 в 17:00)   письмо автору
 
   для: Trianon   (10.05.2007 в 14:10)
 

Спасибо, все отлично работает, только в одном месте не точность

SELECT threads.*, alls.cnt, alls.ldate, last.author AS lauthor 
FROM threads 
LEFT JOIN 
  (SELECT COUNT(id) AS cnt, MAX(add_date) AS ldate,  thread_id 
   FROM messages 
    GROUP BY thread_id) 
  AS alls ON threads.id = alls.thread_id 
  LEFT JOIN messages AS last ON alls.ldate = last.add_date 
ORDER BY ldate DESC, cnt DESC


Все поставил но ничего не понял :) Учить ЭсКюЭл еще и учить...

   
 
 автор: Trianon   (11.05.2007 в 17:56)   письмо автору
 
   для: Temnovit   (11.05.2007 в 17:00)
 

Так тоже можно.
А что, оригинальный вариант выдал ошибку?
Я, честно сказать, запрос не проверял....

   
 
 автор: Temnovit   (11.05.2007 в 18:17)   письмо автору
 
   для: Trianon   (11.05.2007 в 17:56)
 

да, была ошибка

unknown table messages in on cause


Triaton, вы монстр такие запросы с ходу писать :)

   
 
 автор: Trianon   (11.05.2007 в 19:14)   письмо автору
 
   для: Temnovit   (11.05.2007 в 18:17)
 

>да, была ошибка
>unknown table messages in on cause
это потому что разные серверные платформы по-разному трактуют возможность применения псевдонимов для указания полей в отдельных частях sql-запроса.
MSSQL - по одному, MySQL по другому, ORACLE - по третьему....
мне аукается еще и то, что учился я по MSSQL, работать же пришлось на двух других платформах. Никогда не помнишь, как правильно :)

>
>Triaton, вы монстр такие запросы с ходу писать :)
На самом деле, чтобы их писать, нужно чувствовать очень немногое.
1. Что такое агрегатные функции
2. Что такое GROUP BY и как оно взаимодействует с ними
3. что такое JOIN ... ON и LEFT JOIN ON
4. что сформулированный селект может служить таблицей.
И всё пожалуй.

Правда и это позволяет писать довольно много достаточно эффективных запросов. По сравнению с простейшими.

Увы, тонкости SQL - стократ шире.
Увы потому что я ими не владею.
Пока не владею.

   
 
 автор: Temnovit   (14.05.2007 в 15:00)   письмо автору
 
   для: Trianon   (11.05.2007 в 19:14)
 

Никогда не понимал, что можно написать в 1000 страничных книах по SQL, которые встречаются в магазинах. Теперь понимаю :)

   
 
 автор: dima_s_d_s   (21.05.2007 в 13:10)   письмо автору
 
   для: Temnovit   (14.05.2007 в 15:00)
 

Кто может дать комментари к даному запросу (разложить всё по полочкам)?

   
 
 автор: Trianon   (21.05.2007 в 13:18)   письмо автору
 
   для: dima_s_d_s   (21.05.2007 в 13:10)
 

Запрос, таблица результата которого, обозначена как alls


SELECT COUNT(id) AS cnt, MAX(add_date) AS ldate,  thread_id  
   FROM messages  
    GROUP BY thread_id

- этот запрос вопросов не вызывает?
Если вызывает, то какие?

   
 
 автор: dima_s_d_s   (21.05.2007 в 13:29)   письмо автору
 
   для: Trianon   (21.05.2007 в 13:18)
 

В этом запросе незнаю что делает COUNT и MAX, а сама структура запроса понятна

>

>SELECT COUNT(id) AS cnt, MAX(add_date) AS ldate,  thread_id  
>   FROM messages  
>    GROUP BY thread_id
>

   
 
 автор: Trianon   (21.05.2007 в 13:36)   письмо автору
 
   для: dima_s_d_s   (21.05.2007 в 13:29)
 

Отлично.
COUNT(id) определяет количество строк, попадающих в группу с определенным thread_id
MAX(add_date) вычисляет максимальное значение поля add_date, встретившееся в таких строках,
результатом будет таблица из трех столбиков ( id_темы, число_сообщений_темы, дата_последнего сообщения)
Таблица будет обозначена как alls.

   
 
 автор: dima_s_d_s   (21.05.2007 в 13:52)   письмо автору
 
   для: Trianon   (21.05.2007 в 13:36)
 

Пробовал сам решить сложившуюся задачу, но не могу проблема в GROUP BY
вот у меня есть такой запрос к БД



SELECT news.news_title  AS news_title, news.news_id AS news_id, news.news_comments_counter AS news_comments_counter FROM news, news_comments
WHERE news.news_id = news_comments.news_comments_news_id 
GROUP BY news.news_date ORDER BY news_comments.news_comments_date DESC limit 10"; 



Вся проблема заключается в том, что GROUP BY news.news_date группирует записи и при этом не верно определяет последнюю дату (мне нужно, чтоб вывод основывался на последней дате) если я уберу GROUP BY news.news_date то работает всё верно, но тогда выводятся повторения

Фух, не знаю понятно объяснил или нет!

   
 
 автор: Trianon   (21.05.2007 в 14:10)   письмо автору
 
   для: dima_s_d_s   (21.05.2007 в 13:52)
 

Запрос семантически двусмысленнен. Сервер MySQL плюет на двусмысленность, (cheops, как я заметил - тоже :-) и выдает любую из строк в качестве результата. Но я - не сервер, и я такого запроса просто не понимаю.

Вы заказали группировку по news.news_date . Это значит, что весь набор строк будет разбит на группы по датам. От каждой группы нужно получить по одному затребованному в SELECT значению поля..
Но Вы просите поля, которые не входят в объявление группы (и не вычисляются агрегатно, как MAX например) - а значит могут быть разными в разных строках одной группы.

Из какой из строк брать значение? Я не понимаю смысла этого запроса.

   
 
 автор: dima_s_d_s   (21.05.2007 в 14:17)   письмо автору
 
   для: Trianon   (21.05.2007 в 14:10)
 

Я немного ошибся, сори


SELECT news.news_title  AS news_title, news.news_id AS news_id, news.news_comments_counter AS news_comments_counter FROM news, news_comments 
WHERE news.news_id = news_comments.news_comments_news_id  
GROUP BY news.news_title ORDER BY news_comments.news_comments_date DESC limit 10";  


Я хочу, чтоб он группировал их в порядке возрастания, например к новости, 1 было дано 20 комментариев, а к новости 30 было дано 2, причём последним комментом был коммент к новости 1, но в этом случаи он все равно выведет 30 новость

>Из какой из строк брать значение? Я не понимаю смысла этого запроса.
Просто надо вывести заголовок и id новости с последним комментарием

   
 
 автор: Trianon   (21.05.2007 в 15:41)   письмо автору
 
   для: dima_s_d_s   (21.05.2007 в 14:17)
 

>>Из какой из строк брать значение? Я не понимаю смысла этого запроса.
>Просто надо вывести заголовок и id новости с последним комментарием

Это задача в общем виде.
Приведенный запрос её не решает. Почему - я сказал выше. Он неоднозначен.
Сервер не человек, чтобы догадываться о намерениях, задачу ему нужно ставить четко.

   
 
 автор: dima_s_d_s   (21.05.2007 в 15:55)   письмо автору
 
   для: Trianon   (21.05.2007 в 15:41)
 

Тогда сделаем так.
Допустим есть такой запрос:


SELECT news.news_title  AS news_title, news.news_id AS news_id, news.news_comments_counter AS news_comments_counter FROM news, news_comments  
WHERE news.news_id = news_comments.news_comments_news_id   
ORDER BY news_comments.news_comments_date DESC limit 10";   


Теперь стоит вопрос сгрупировать все одинаковые новости

   
 
 автор: Trianon   (21.05.2007 в 16:02)   письмо автору
 
   для: dima_s_d_s   (21.05.2007 в 15:55)
 

в каком смысле - сгруппировать?

   
 
 автор: dima_s_d_s   (21.05.2007 в 16:21)   письмо автору
 
   для: Trianon   (21.05.2007 в 16:02)
 

при выводе будет такое

1. как похудеть [10]
2. ЧПУ [2]
3. Как похудеть [10]
4. MSQ [1]
5. Кадеты [32]
6 Кадеты [32
7 Кадеты [32]
8 Кадеты [32]
9 Как похудеть [10]
10 Кадеты [32]

Тоесть тот скрипт выведет последних 10 комментариев.

Я хочу чтоб он вывел так:
1. как похудеть [10]
2. ЧПУ [2]
4. MSQ [1]
5. Кадеты [32]

Примерно так

   
 
 автор: Trianon   (21.05.2007 в 16:36)   письмо автору
 
   для: dima_s_d_s   (21.05.2007 в 15:55)
 

news.news_comments_counter - это поле таблицы?

   
 
 автор: dima_s_d_s   (21.05.2007 в 16:49)   письмо автору
 
   для: Trianon   (21.05.2007 в 16:36)
 

Да
news_comments_counter - количество комментариев

   
 
 автор: Trianon   (21.05.2007 в 16:53)   письмо автору
 
   для: dima_s_d_s   (21.05.2007 в 16:49)
 

Тогда почему не добавить еще одно поле
news.news_comments_lasttime - время последнего коментария ?
тогда строить соединеие двух таблиц вообще не потребуется.

   
 
 автор: dima_s_d_s   (21.05.2007 в 16:55)   письмо автору
 
   для: Trianon   (21.05.2007 в 16:53)
 

эта идея мне приходила в колову! Но просто уже сильно много комментов накопилось!

   
 
 автор: Trianon   (21.05.2007 в 16:58)   письмо автору
 
   для: dima_s_d_s   (21.05.2007 в 16:55)
 

Какая разница?
Считать то всё равно запрос будет.

   
 
 автор: dima_s_d_s   (21.05.2007 в 17:00)   письмо автору
 
   для: Trianon   (21.05.2007 в 16:58)
 

Я так понял это и всё!
Спасибо за помощь, буду думать как всётаки сделать!!!

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования