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

Форум MySQL

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

 

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

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

тема: Функции группировки в MySQL
 
 автор: SportSoft   (06.06.2008 в 12:34)   письмо автору
 
 

Есть таблица с полями:

`id` int,
`referer_id` int,
`status` enum('good', 'semi-good', 'bad'),
`text` varchar,
`date` int,
PRIMARY KEY `id`

Примерный запрос того, что есть:

SELECT `id`, `referer_id`, `status`, `text`, `date`, MAX(`date`) AS `max_date`, COUNT(`id`) AS `count` FROM `table` GROUP BY `referer_id` ORDER BY `date` DESC;

Вся проблема в том, что всегда по разному достается `text`, `date` для группы. А нужно, чтобы доставался тест с status = 'good', а группа учитывала status = 'good' или status = 'semi-good'.
Если применять WHERE, то группа неправильно считает. Выражение HAVING тоже не смог правильно применить.

А сделать все нужно в один запрос.

   
 
 автор: Trianon   (06.06.2008 в 13:55)   письмо автору
 
   для: SportSoft   (06.06.2008 в 12:34)
 

>SELECT `id`, `referer_id`, `status`, `text`, `date`, MAX(`date`) AS `max_date`, COUNT(`id`) AS `count` FROM `table` GROUP BY `referer_id` ORDER BY `date` DESC;
>
>Вся проблема в том, что всегда по разному достается `text`, `date` для группы.
По большому счету, Вы не имеете права в SELECT-списке указывать поля отсутствующие в GROUP BY без применения агрегатных функций. Запрос в этом случае становится неопределенным.

К сожалению, сказать что-то большее не получится - Ваша задача совершенно неясна. Хотя бы потому, что никакая группа ничего не считает.
Конструкция GROUP BY field заставляет сервер перед вычислением агрегатных функций разбить всю табличную выборку на группы, по одной на каждое значение (или сочетание значений) field.
После этого, для каждой группы вычисляется по одной строке. Формально, строки эти не могут содержать никаких полей, кроме группирующих, и значений агрегатных функций. У Вас же таких полей полно - id, status, text, date
Конструкция WHERE применяется до разбиения на группы. Конструкция HAVING - после вычисления агрегатов.

   
 
 автор: SportSoft   (06.06.2008 в 14:12)   письмо автору
 
   для: Trianon   (06.06.2008 в 13:55)
 

Trianon, то есть вместе с группирующими полями никогда нельзя подставлять обычные? :(

Поясню подробнее:
мне нужно вначале сгруппировать по REFERER_ID и получить количество с одинаковым REFERER_ID с типом good или semi-good. И плюсом выбрать к этим группам дополнительные их уникальные параметры-свойства (date, text), которые берутся из этой же группы, только им соответствует статус = 'good' (для любой группы со статусом GOOD может быть только одна заапись).

В данном случае если я использую WHERE status = good, то уникальные свойства выбираются правильно, но для группы подсчет неверен (так как не берется + status = semigood.
Если вообще не использовать WHERE, тогда подсчет ведется правильно, а уникальные параметры раз от раза меняются.

   
 
 автор: Trianon   (06.06.2008 в 14:26)   письмо автору
 
   для: SportSoft   (06.06.2008 в 14:12)
 

>Trianon, то есть вместе с группирующими полями никогда нельзя подставлять обычные? :(
Не подставлять, а выбирать.
В нормальных СУБД - нельзя.
В MySQL - можно, но безо всякой надежды получить осмысленный результат.
Потому что запрос становится неоднозначным.

>Поясню подробнее:
>мне нужно вначале сгруппировать по REFERER_ID и получить количество с одинаковым REFERER_ID с типом good или semi-good.

SELECT referer_id, COUNT(referer_id) 
  FROM tbl
  WHERE status = 'good' OR status = 'semi-good' 
  GROUP BY referer_id;


>И плюсом выбрать к этим группам дополнительные их уникальные параметры-свойства (date, text), которые берутся из этой же группы, только им соответствует статус = 'good' (для любой группы со статусом GOOD может быть только одна заапись).

Если я правильно понял, то как-то так:

SELECT g.referer_id AS g_rid, g.cnt, t.* 
  FROM 
    (SELECT referer_id, COUNT(referer_id) AS cnt
      FROM tbl
      WHERE status = 'good' OR status = 'semi-good' 
      GROUP BY referer_id;
    ) AS g
   LEFT JOIN tbl AS t ON g.referer_id = t.referer_id  AND t.status='good'

   
 
 автор: SportSoft   (06.06.2008 в 15:41)   письмо автору
 
   для: Trianon   (06.06.2008 в 14:26)
 

Как-то так получилось вроде. :)

Спасибо большое. :)

   
Rambler's Top100
вверх

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