如何使用sql子查询进行分组

时间:2011-06-03 09:53:02

标签: mysql sql

我现在想不清楚,我想通过station_id返回计数,输出的例子是:

第1站有3个fb帖子,6个linkedin帖子,5个电子邮件帖子 站2有3个fb帖子,6个linkedin帖子,5个电子邮件帖子

所以我需要按站ID分组,我的表结构是

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个linkedin帖子返回,当它有一个(db tho中有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 个答案:

答案 0 :(得分:14)

或者,最快的方法,避免连接和子选择以您想要的确切格式获取它:

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 |
+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+

答案 1 :(得分:2)

正如gnif的回答所暗示的,有三个相关的子查询具有性能开销。根据您使用的DBMS,它可能与自我加入三次类似。

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

答案 2 :(得分:1)

放手一搏:

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 |
+------------+----------+----------+

答案 3 :(得分:0)

试试这个:

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