简体   繁体   English

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

[英]how to group by with a sql subqueries

I can't think clearly at the moment, I want to return counts by station_id, an example of output would be:我现在想不清楚,我想通过 station_id 返回计数,output 的一个例子是:

station 1 has 3 fb post, 6 linkedin posts, 5 email posts station 2 has 3 fb post, 6 linkedin posts, 5 email posts第 1 站有 3 个 fb 帖子,6 个linkedin 帖子,5 个 email 帖子 第 2 站有 3 个 fb 帖子,6 个linkedin 帖子,5 个 email 帖子

So I need to group by the station id, my table structure is所以我需要按站号分组,我的表结构是

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 ;

The query I have so far is returning station 0 as having 2 linkedin posts when it has one (2 in the db tho)到目前为止,我的查询是返回站 0,因为它有一个(数据库中的 2 个)有 2 个linkedin 帖子

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;

Or, the fastest way, avoiding joins and subselects to get it in the exact format you want:或者,最快的方法是避免连接和子选择以获取您想要的确切格式:

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;

Outputs:输出:

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

You may also want to put an index on there to speed it up您可能还想在其中放置一个索引以加快速度

ALTER TABLE posts ADD INDEX (station_id, type);

Explain output:解释output:

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

As implied by gnif's answer, having three correlated sub_queries has a performance over-head.正如 gnif 的回答所暗示的那样,拥有三个相关的 sub_queries 会产生性能开销。 Depending on the DBMS you're using, it could perform similarly to having a self join three times.根据您使用的 DBMS,它的执行类似于 3 次自联接。

gnif's methodology ensures that the table is only parsed once, without the need for joins, correlated sub_queries, etc. gnif 的方法确保表只解析一次,而不需要连接、相关子查询等。

The immediately obvious down-side of gnif's answer is that you don't ever get records for 0's. gnif 的答案最明显的缺点是你永远不会得到 0 的记录。 If there are no fb types, you just don't get a record.如果没有 fb 类型,您就不会获得记录。 If that is not an issue, I'd go with his answer.如果这不是问题,我会 go 回答他。 If it is an issue, however, here is a version with similar methodology to gnif, but matching your output format...但是,如果这是一个问题,这里有一个与 gnif 方法相似的版本,但与您的 output 格式匹配...

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

Give this a go:给这个 go:

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

The output format will be a little different to what your attempting to get, but it should provide the statistics your trying to retrieve. output 格式与您尝试获取的格式略有不同,但它应该提供您尝试检索的统计信息。 Also since its a single query it is much faster.此外,由于它是一个单一的查询,它要快得多。

-- Edit, added example result set -- 编辑,添加示例结果集

+------------+----------+----------+
| station_id | type     | count(*) |
+------------+----------+----------+
| 1          | fb       |        2 |
| 1          | linkedin |        3 |
| 1          | email    |        5 |
| 2          | linkedin |        2 |
| 2          | email    |        1 |
+------------+----------+----------+

try this:尝试这个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM