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

Форум MySQL

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

 

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

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

тема: Группировка в многотабличном запросе
 
 автор: JIEXA   (02.09.2007 в 03:49)   письмо автору
 
 

Есть таблицы
comments
comment_id
comment_news_id
comment_datepost

news
news_id
news_subject
news_community
news_public

community
community_id
community_alias

Нужно показать последние 15 комментариев, только чтобы если к примеру к 1 новости больше 2 комментариев, то они не дублировались. Я попробывал так:


    SELECT comments.comment_id,comments.comment_datepost, news.news_subject, community.community_alias 
    FROM comments
    LEFT JOIN news ON news.news_id=comments.comment_news_id
    LEFT JOIN community ON community.community_id=news.news_community
    WHERE news.news_public='Y'
    GROUP BY news.news_id
    ORDER BY comments.comment_datepost DESC 
    LIMIT 15


Выводяться только уникальные записи, но они почему-то упорядочеваються не так как надо. Точнее они упорядочиваються по дате первого комментария к новости, а не по дате последнего. Почему так - не понимаю, вроде всё правильно написал. Подскажите пожалуйста.

   
 
 автор: cheops   (02.09.2007 в 11:25)   письмо автору
 
   для: JIEXA   (02.09.2007 в 03:49)
 

Когда происходит группировка, MySQL берёт первую попавшуюся запись, удовлетворяющую конструкции GROUP BY - этой записью зачастую оказывается первая запись (однако это не гарантируется).

   
 
 автор: JIEXA   (02.09.2007 в 17:07)   письмо автору
 
   для: cheops   (02.09.2007 в 11:25)
 

Как я понял сначало идет группировка, а потом уже ORDER... Как можно выйти из ситуации?

   
 
 автор: cheops   (02.09.2007 в 19:40)   письмо автору
 
   для: JIEXA   (02.09.2007 в 17:07)
 

Разбивать многотабличный запрос на однотабличные.

   
 
 автор: Trianon   (03.09.2007 в 22:40)   письмо автору
 
   для: JIEXA   (02.09.2007 в 03:49)
 

>------
SELECT comments.comment_id,comments.comment_datepost, news.news_subject, community.community_alias
FROM comments
LEFT JOIN news ON news.news_id=comments.comment_news_id
LEFT JOIN community ON community.community_id=news.news_community
WHERE news.news_public='Y'
GROUP BY news.news_id
ORDER BY comments.comment_datepost DESC
LIMIT 15
>-----
В SELECT-разделе группирующего запроса присутствуют выражения, отличные от полей группировки и агрегирующих функций над строками выборки. Формально - запрос неопределен.

   
 
 автор: oradev   (04.09.2007 в 13:03)   письмо автору
 
   для: Trianon   (03.09.2007 в 22:40)
 

Trianon, нет ну всегда старый бабушкни метод можно сыскать:)

SELECT comm.comm_id, n.news_subject, comm.comment_news_id, comm.c_date,
       community.community_alias
  FROM news n
       JOIN
       (SELECT   comment_news_id, MAX (comment_datepost) c_date,
                 TO_NUMBER (SUBSTR (MAX (comment_datepost || '~' || comment_id),
                                    LENGTH (MAX (comment_datepost)) + 2
                                   )
                           ) comm_id
            FROM comments
        GROUP BY comment_news_id
        ORDER BY 2 DESC) comm ON (n.news_id = comm.comment_news_id)
       JOIN community ON (community.community_id = n.news_community)
 WHERE n.news_public = 'Y';


P.S. Югра многоликая, делами великая идет вдохновенно вперед!

   
 
 автор: Trianon   (04.09.2007 в 16:54)   письмо автору
 
   для: oradev   (04.09.2007 в 13:03)
 

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

А уж если делать, так по-большому.

Старый дедушкин метод. Сегодня (surprise!) по шагам :))

-- 1. Выбираем даты последних коментариев к интересующим новостям: sel1:

  SELECT news.news_id AS nid,  MAX(comments.comment_datepost) AS mdp,
    FROM news
    LEFT JOIN comments ON news.news_id=comments.comment_news_id
   WHERE news.news_public='Y'
   GROUP BY news.news_id
-- 2. Выбираем сами новости согласно дат коментариев, опираясь на предыдущий запрос sel1:

 SELECT c.comment_id,c.comment_datepost, n.news_subject, t.community_alias
   FROM news as n
          JOIN sel1 ON n.news_id = sel1.nid
          JOIN comments as с ON sel1.mdp = c.comment_datepost
     LEFT JOIN community ON n.news_community=community.community_id
   ORDER BY mdp DESC
   LIMIT 15
-- 3. Склеиваем всё вместе:

 SELECT c.comment_id,c.comment_datepost, n.news_subject, t.community_alias
   FROM news as n
          JOIN (
            SELECT news.news_id AS nid,  MAX(comments.comment_datepost) AS mdp,
              FROM news
              LEFT JOIN comments ON news.news_id=comments.comment_news_id
             WHERE news.news_public='Y'
             GROUP BY news.news_id

            ) AS sel1 ON n.news_id = sel1.nid
          JOIN comments as с ON sel1.mdp = c.comment_datepost
     LEFT JOIN community ON n.news_community=community.community_id
   ORDER BY mdp DESC
   LIMIT 15

   
 
 автор: oradev   (05.09.2007 в 10:48)   письмо автору
 
   для: Trianon   (04.09.2007 в 16:54)
 

Вот здесь:

SELECT news.news_id AS nid,  MAX(comments.comment_datepost) AS mdp, 
              FROM news 



И вот здесь

 ON sel1.mdp = c.comment_datepost 


Мне не нравится

   
 
 автор: Trianon   (05.09.2007 в 11:17)   письмо автору
 
   для: oradev   (05.09.2007 в 10:48)
 

Ключевые слова AS в назначениях алиасов полям результирующего набора строк можете опустить - Вам так привычнее.
А что не нравится в условии соединения?

Возможность зацепить несколько строк с одинаковым таймштампом? Разве только это...

   
 
 автор: Trianon   (05.09.2007 в 12:17)   письмо автору
 
   для: oradev   (05.09.2007 в 10:48)
 

Так... по-моему понял.
Не нравится то, что выборка идет не по ключевому столбцу.
Тогда, в предположении, что comment_id - автоинкрементный первичный ключ, возрастающий параллельно таймштампу, вот такой вариант:

SELECT c.comment_id,c.comment_datepost, n.news_subject, t.community_alias 
   FROM news as n 
          JOIN ( 
            SELECT news.news_id AS nid,  MAX(comments.comment_id) AS mcid, 
              FROM news 
              LEFT JOIN comments ON news.news_id=comments.comment_news_id 
             WHERE news.news_public='Y' 
             GROUP BY nid

            ) AS sel1 ON n.news_id = sel1.nid 
          JOIN comments as с ON sel1.mcid = c.comment_id 
     LEFT JOIN community ON n.news_community=community.community_id 
   ORDER BY mdp DESC 
   LIMIT 15 


И повторов не будет всяко. primary key есть primary key.

   
 
 автор: oradev   (05.09.2007 в 12:48)   письмо автору
 
   для: Trianon   (05.09.2007 в 12:17)
 

--> Не нравится то, что выборка идет не по ключевому столбцу.

Trianon, само собой, это чистая магия данных:


ON sel1.mdp = c.comment_datepost  


А вот мне тем более не нравится! Это та же магия данных !


sel1.mcid = c11.comment_id

   
 
 автор: Trianon   (05.09.2007 в 12:51)   письмо автору
 
   для: oradev   (05.09.2007 в 12:48)
 

Что Вы имеете в виду?
Я, ей-богу, не понял, где плохо и в чем?

   
 
 автор: oradev   (05.09.2007 в 12:57)   письмо автору
 
   для: Trianon   (05.09.2007 в 12:51)
 

объясните мне сокральный смысл вот этого:

 SELECT news.news_id nid,  MAX(comments.comment_id) mcid


Я правильно понял, этот запрос призван выводить то что хочет афтор ?

   
 
 автор: oradev   (05.09.2007 в 13:40)   письмо автору
 
   для: oradev   (05.09.2007 в 12:57)
 

Кстати Насчет сюрприза, вместо моего бабушкина метода, можно использовать и такой.
Но увы Мускул его поддерживать не будет:

SELECT comm.comm_id, n.news_subject, comm.comment_news_id, comm.c_date,
       community.community_alias
  FROM news n
       JOIN
       (SELECT   comment_news_id, MAX (comment_datepost) c_date,
                 MAX (comment_id)KEEP (DENSE_RANK LAST ORDER BY comment_datepost) comm_id
            FROM comments
        GROUP BY comment_news_id ORDER BY 2) comm ON (n.news_id = comm.comment_news_id)
       JOIN community ON (community.community_id = n.news_community)
 WHERE n.news_public = 'Y';


А на Ораклях версии выше 8.1.2 он проходит. Ну этоя к вопросу когда наконец-то Мускул начнет поддержку аналитических функций.

   
 
 автор: Trianon   (05.09.2007 в 16:08)   письмо автору
 
   для: oradev   (05.09.2007 в 12:57)
 

>объясните мне сокральный смысл вот этого:
>

> SELECT news.news_id nid,  MAX(comments.comment_id) mcid
>

>
>Я правильно понял, этот запрос призван выводить то что хочет афтор ?
Сакральный смысл этого проявляется лишь вкупе с GROUP BY nid.
Это получение отношения ключей новостей последним коменариям.
GROUP BY здесь вполне крректный, поскольку ничего, кроме группирующего поля и агрегата над строками я от сервера не прошу.

Автор же хочет получить с новостей не только ключи, но и кучу другой подключевой информации. Отсюда соединение с нужными таблицами на более верхнем уровне.

   
 
 автор: oradev   (07.09.2007 в 13:12)   письмо автору
 
   для: Trianon   (05.09.2007 в 16:08)
 

Trianon, только сейчас вспомнил об этом топике. Мне реализацию в подробностях не нужно., ибо решение схожее с моим. Относительно первого насчет соединения дат, там но коммент
Касаемо вот этого:

SELECT news.news_id nid,  MAX(comments.comment_id) mcid 
......

судя по логике так оно конечно, но в принципе опять магия данных.
Хотя судя по топика афтора ему этого хватит переварить:)

   
 
 автор: Trianon   (07.09.2007 в 13:29)   письмо автору
 
   для: oradev   (07.09.2007 в 13:12)
 

Вас не затруднит честно рассказать, что Вы понимаете под термином "магия данных"?

Магия, насколько мне известно - общее обозначение нематериальных/нетехнологических методик взаимодействия человека с окружающим миром.

В моем запросе ничего нетехнологического нету. Всё идет через соответствующим образом материализованные протоколы.

   
 
 автор: oradev   (07.09.2007 в 13:49)   письмо автору
 
   для: Trianon   (07.09.2007 в 13:29)
 

comments

comment_id comment_news_id comment_datepost
1 5 14.01.2007
2 5 13.01.2007
3 5 11.01.2007


?

   
 
 автор: Trianon   (07.09.2007 в 14:03)   письмо автору
 
   для: oradev   (07.09.2007 в 13:49)
 

ну уж нет. Играть мы будем по местным правилам.
comment_id comment_news_id comment_datepost

1 5 2007-01-11 15:25:07
3 5 2007-01-14 23:48:25
2 5 2007-01-13 08:12:49



Впрочем, на ситуацию с comment_id формат даты влиять не будет.

   
Rambler's Top100
вверх

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