как сгруппировать с подзапросами sql - PullRequest
4 голосов
/ 03 июня 2011

В данный момент я не могу ясно представить себе, я хочу вернуть счетчики по station_id, пример вывода:

станция 1 имеет 3 поста в фб, 6 постов в постах, 5 постов по электронной почте на станции 2 есть 3 поста в фб, 6 постов в мыслях, 5 постов по электронной почте

Так что мне нужно сгруппировать по идентификатору станции, моя структура таблицы

CREATE TABLE IF NOT EXISTS `posts` (
  `post_id` bigint(11) NOT NULL auto_increment,
  `station_id` varchar(25) NOT NULL,
  `user_id` varchar(25) NOT NULL,
  `dated` datetime NOT NULL,
  `type` enum('fb','linkedin','email') NOT NULL,
  PRIMARY KEY  (`post_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=x ;

На данный момент у меня есть запрос, возвращающий станцию ​​0 с двумя сообщениями с сообщением о причине, когда она есть (2 в базе данных)

SELECT Station_id, (select count(*) FROM posts WHERE type = 'linkedin') AS linkedin_count, (select count(*) FROM posts WHERE type = 'fb') AS fb_count, (select count(*) FROM posts WHERE type = 'email') AS email_count  FROM `posts` GROUP BY station_id;

Ответы [ 4 ]

14 голосов
/ 03 июня 2011

Или, самый быстрый способ, избегая объединений и вложенных элементов, чтобы получить его в нужном формате:

SELECT
  station_id,
  SUM(CASE WHEN type = 'linkedin' THEN 1 ELSE 0 END) AS 'linkedin',
  SUM(CASE WHEN type = 'fb'       THEN 1 ELSE 0 END) AS 'fb',
  SUM(CASE WHEN type = 'email'    THEN 1 ELSE 0 END) AS 'email'
FROM posts
GROUP BY station_id;

Выходы:

+------------+----------+------+-------+
| station_id | linkedin | fb   | email |
+------------+----------+------+-------+
| 1          |        3 |    2 |     5 |
| 2          |        2 |    0 |     1 |
+------------+----------+------+-------+

Вы также можете добавить туда индекс, чтобы ускорить его

ALTER TABLE posts ADD INDEX (station_id, type);

Объяснить вывод:

+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+
|  1 | SIMPLE      | posts | index | NULL          | station_id | 28      | NULL |   13 | Using index |
+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+
2 голосов
/ 03 июня 2011

Как следует из ответа gnif, наличие трех взаимосвязанных подзапросов снижает производительность. В зависимости от используемой СУБД, она может работать аналогично автоматическому соединению три раза.

Методология gnif гарантирует, что таблица анализируется только один раз, без необходимости объединения, коррелированных подзапросов и т. Д.

Непосредственно очевидным недостатком ответа gnif является то, что вы никогда не получите записи для 0. Если нет типов fb, вы просто не получите запись. Если это не проблема, я бы пошел с его ответом. Однако, если это проблема, вот версия с методологией, аналогичной gnif, но соответствующей вашему выходному формату ...

SELECT
  station_id,
  SUM(CASE WHEN type = 'linkedin' THEN 1 ELSE 0 END) AS linkedin_count,
  SUM(CASE WHEN type = 'fb'       THEN 1 ELSE 0 END) AS fb_count,
  SUM(CASE WHEN type = 'email'    THEN 1 ELSE 0 END) AS email_count
FROM
  posts
GROUP BY
  station_id
1 голос
/ 03 июня 2011

Попробуйте:

SELECT station_id, type, count(*) FROM posts GROUP BY station_id, type

Формат вывода будет немного отличаться от того, что вы пытаетесь получить, но он должен предоставлять статистику, которую вы пытаетесь получить.Кроме того, поскольку это один запрос, он намного быстрее.

- Изменить, добавлен пример набора результатов

+------------+----------+----------+
| station_id | type     | count(*) |
+------------+----------+----------+
| 1          | fb       |        2 |
| 1          | linkedin |        3 |
| 1          | email    |        5 |
| 2          | linkedin |        2 |
| 2          | email    |        1 |
+------------+----------+----------+
0 голосов
/ 03 июня 2011

попробуйте это:

SELECT p.Station_id, 
(select count(*) FROM posts WHERE type = 'linkedin' and station_id=p.station_id) AS linkedin_count, 
(select count(*) FROM posts WHERE type = 'fb' and station_id=p.station_id) AS fb_count, 
(select count(*) FROM posts WHERE type = 'email' and station_id=p.station_id) AS email_count 
FROM `posts` p GROUP BY station_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...