Соединение SQL и множественное количество (*)?

#mysql #sql

#mysql #sql

Вопрос:

У меня есть groups_areas , groups , groups_members , groups_logs таблицы. Я хочу перечислить все группы в области с описанием и т. groups Д., А Также статистику из groups_members и groups_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;
  

Проблема, на мой взгляд, заключается в том, что мне нужно как-то соотнести идентификатор каждой группы из первого запроса с идентификатором группы второго набора подзапросов. Предоставление мне результирующего набора 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. Используете ли вы здесь как MySQL, так и Postgresql?

2. не могли бы вы поделиться своей структурой таблицы?

3. нет jarlh, изменен тег

4. 1) Что вы подразумеваете под статистикой? 2) Пожалуйста, предоставьте образцы данных и ожидаемый результат на основе этих образцов данных.

5. Под статистикой я подразумеваю два count(*) .

Ответ №1:

Использование левых соединений и отдельных счетчиков.

 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;
  

Или без группы by. Присоединение к подзапросам.
Это может быть медленнее при поиске в одной области, но может быть быстрее для всех областей.

 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);
  

Комментарии:

1. Для меня они дают разные результаты, второй работает нормально. Спасибо

2. Немного изменил их. Вместо полей идентификатора теперь они оба считаются разными для этого журнала и идентификатора участника. Оба дали одинаковые результаты на основе ваших тестовых данных.

3. Они оба работают. Я записал это несколько раз, жестко закодировал его в память, имеет смысл. Еще раз спасибо.