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]   

> Без описания
Zuldek
Отправлено: 11 Ноября, 2014 - 19:18:55
Post Id


Постоянный участник


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


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




Добрый вечер.

Пусть есть таблица просмотров поста юзерами на определённом статусе. Задача получить количество просмотров поста по статусам. при этом для всех статусов при просмотре в лог пишется 0 или 1 и их считаем простым sum, а для учета веса юзеров смотревших пост (1 - 40) в таблицу просто пишется сам вес (1-40) и нужно в агрегированной записи выборки получить сгрупированные значения просмотров: "вес (кол-во)" по каждому имеющемуся для поста весу
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| post_id | int(11) | YES | | NULL | |
| current_week | int(2) | YES | | NULL | |
| status1 | int(1) | YES | | NULL | |
| status2 | int(1) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+

Записи в логе выглядят примерно так:

123 | 0 | 1 | 15
100 | 1 | 1 | 20
101 | 0 | 0 | 20
101 | 0 | 0 | 0

Задача получить одним запросом сгруппрованные данные формата:

post_id | sum(ststus1) | sum(status2) | 15(4), 10(2), 40(6)

Запрос:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT post_id, SUM(status1), SUM(status2), GROUP_CONCAT(weight, '(0)' SEPARATOR ', ') FROM tblname GROUP BY post_id;

даёт выборку:
'210', '5', '0', '15(0), 0(0), 20(0), 1(0), 15(0), 20(0)'
Соответственно вместо '(0)' и дублирующихся значений веса хотелось бы получить их количество максимально лаконичным способом.

Кроме этажных подзапросов ничего не приходит в голову.
 
 Top
Мелкий Супермодератор
Отправлено: 11 Ноября, 2014 - 20:06:58
Post Id



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


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


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




CODE (SQL):
скопировать код в буфер обмена
  1. SELECT post_id, SUM(status1), SUM(status2), GROUP_CONCAT(weight_sep SEPARATOR ', ') FROM
  2. (SELECT post_id, SUM(status1) AS status1, SUM(status2) AS status2, concat(weight,' (',count(0),')') AS weight_sep FROM tblname
  3. GROUP BY post_id, weight
  4. ) ws
  5. GROUP BY post_id;

Подзапрос, но только один этаж.

PS: а то что все поля могут быть null это баг или зачем-то нужно?


-----
PostgreSQL DBA
 
 Top
Zuldek
Отправлено: 12 Ноября, 2014 - 09:42:02
Post Id


Постоянный участник


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


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




Нет NN они.
Примерно к такому и пришёл только исключив вес '0'.
Тут окончательно можно судить об эффективности только агрегируя большой лог. Потестирую на бою, посмотрим что покажет.
Изначально когда только ставилась задача был против такой структуры. Ибо имхо тут в разы проще хранить просмотры по весам в отдельной таблице, а осталньые статусы просто суммируя с группировкой по id. Единственный минус это join конечно будет.
 
 Top
Zuldek
Отправлено: 02 Декабря, 2014 - 09:58:30
Post Id


Постоянный участник


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


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




В продолжении задачи.
Позже выяснилось, что таких параметров, как weight, для которых нужна группировка, оказывается ещё 2.
Не нашёл ничего лучше, как сделать отдельные запросы с их подсчётом чтобы не городить огород:
минус понятен: склеивание массивов в пыхе для дальнейшего обхода.

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT post_id, GROUP_CONCAT(weight_2_sep SEPARATOR ', ') FROM
  2.     (SELECT post_id, concat(
  3. weight_2,' (',count(0),')') AS weight_2_sep FROM tbl_name WHERE weight_2 != 0
  4.     GROUP BY post_id, weight_2
  5.     ) ws
  6.     GROUP BY post_id
  7.  
  8. SELECT post_id, GROUP_CONCAT(weight_3_sep SEPARATOR ', ') FROM
  9.     (SELECT post_id, concat(
  10. weight_3,' (',count(0),')') AS weight_3_sep FROM tbl_name WHERE weight_3 != 0
  11.     GROUP BY post_id, weight_2
  12.     ) ws
  13.     GROUP BY post_id

Плюс в том что в этих запросах можно исключить нулевые значения WHERE weight_3 != 0, в отличии от первого запроса ибо там !=0 использовать нельзя чтобы банально получить все post_id.

(Отредактировано автором: 02 Декабря, 2014 - 10:00:53)

 
 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