SQL连接和多次计数(*)?

时间:2016-10-07 12:56:08

标签: mysql sql

我有groups_areasgroupsgroups_membersgroups_logs个表格。 我想列出某个区域中的所有群组,其中的描述等来自groups以及来自groups_membersgroups_logs的统计信息。这是我的:

SELECT name, description
FROM groups g
INNER JOIN groups_areas ga ON ga.groupid = g.id WHERE ga.area = ?; 

SELECT (SELECT COUNT(*)
FROM groups_members gm
WHERE gm.groupid = ?) as members,
      (SELECT COUNT(*) FROM groups_logs gl WHERE gl.groupid = ?) as logs;

我认为问题在于,我需要以某种方式将第一个查询中的每个组ID与第二组子查询的组ID相关联。为该区域中的每个组提供name, description, members, logs的结果集。

表结构(简化):

id (int) | name (text) | description (text)
1          engineering   building things
2          sociology     study of people
3          mining        digging up the earth
4          economics     study of various economic processes

groups_areas

groupid (int) | area (int)
1             2
2             2
3             1
4             3

groups_members

groupid (int) | member (int)
1             1
1             2
2             3
4             3
3             2
3             1

groups_logs

groupid (int) | log (int)
1             1
2             4
3             2
3             3
4             5

成员

id (int) | name (text)
1          max
2          john
3          elf

预期输出将是如下行:

engineering | building things       | 2  | 1
mining | digging up the earth | 2 | 2
...

1 个答案:

答案 0 :(得分:2)

使用左连接和不同计数。

SELECT g.name, g.description, 
COUNT(DISTINCT gm.member) AS members, 
COUNT(DISTINCT gl.log) AS logs
FROM groups g
INNER JOIN groups_areas ga ON (ga.groupid = g.id)
LEFT JOIN groups_members gm ON (gm.groupid = g.id)
LEFT JOIN groups_logs gl ON (gl.groupid = g.id)
WHERE ga.area = ?
GROUP BY g.name, g.description
ORDER BY g.name, g.description;

或者没有一个小组。加入子查询。
在寻找一个区域时,这可能会更慢,但对于所有区域可能会更快。

SELECT g.name, g.description, 
gm.total as members, 
gl.total as logs
FROM groups g
INNER JOIN groups_areas ga ON (ga.groupid = g.id)
LEFT JOIN (
  select groupid, count(distinct member) as total 
  from groups_members
  group by groupid
) gm ON (gm.groupid = g.id)
LEFT JOIN (
  select groupid, count(distinct log) as total 
  from groups_logs
  group by groupid
) gl ON (gl.groupid = g.id)
WHERE ga.area = ?
ORDER BY g.name, g.description;

测试数据

create table groups (id int PRIMARY KEY, name text, description text);
insert into groups values (1,'engineering','building things');
insert into groups values (2,'sociology','study of people');
insert into groups values (3,'mining','digging up the earth');
insert into groups values (4,'economics','study of various economic processes');

create table groups_areas (id int AUTO_INCREMENT PRIMARY KEY, groupid int, area int);
insert into groups_areas (groupid, area) values (1,2);
insert into groups_areas (groupid, area) values (2,2);
insert into groups_areas (groupid, area) values (3,1);
insert into groups_areas (groupid, area) values (4,3);

create table groups_members (id int AUTO_INCREMENT PRIMARY KEY, groupid int, member int);
insert into groups_members (groupid, member) values (1,1);
insert into groups_members (groupid, member) values (1,2);
insert into groups_members (groupid, member) values (2,3);
insert into groups_members (groupid, member) values (4,3);
insert into groups_members (groupid, member) values (3,2);
insert into groups_members (groupid, member) values (3,1);

create table groups_logs (id int AUTO_INCREMENT PRIMARY KEY, groupid int, log int);
insert into groups_logs (groupid, log) values (1,1);
insert into groups_logs (groupid, log) values (2,4);
insert into groups_logs (groupid, log) values (3,2);
insert into groups_logs (groupid, log) values (3,3);
insert into groups_logs (groupid, log) values (4,5);