Есть ли способ найти сумму и совокупное число в этом запросе MYSQL? - PullRequest
1 голос
/ 24 апреля 2020

У меня есть этот MYSQL запрос, который я использую, чтобы найти кумулятивный рост таблицы groups в связанной с ней таблице members с течением времени.

  SELECT DISTINCT g.name, m.created_at,
           COUNT(*) OVER(PARTITION by g.id ORDER BY m.created_at) count
    FROM members m
    INNER JOIN groups g on g.id = m.group_id

Это дает результирующий набор, например:

[
  { 'group01', date: '2019-03-04', count: 5 },
  { 'group01', date: '2019-03-09', count: 12 }
  { 'group01', date: '2019-03-15', count: 23 }
  { 'group02', date: '2019-03-04', count: 3 }
  { 'group01', date: '2019-03-10', count: 19 }
  { 'group01', date: '2019-03-17', count: 27 }
]

Я также хотел бы получить общее количество членов группы. Так что набор данных будет выглядеть так:

[
  { name: 'group01', date: '2019-03-04', count: 5, total: 23 },
  { name: 'group01', date: '2019-03-09', count: 12, total: 23 },
  { name: 'group01', date: '2019-03-15', count: 23, total: 23 },
  { name: 'group02', date: '2019-03-04', count: 3, total: 27 },
  { name: 'group02', date: '2019-03-10', count: 19, total: 27 },
  { name: 'group02', date: '2019-03-17', count: 27, total: 27 }
]

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

Есть ли способ сделать это?

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

Просто добавьте еще один столбец к результирующему набору, который подсчитывает количество окон по тому же partition, но без предложения order by; это приводит к тому, что база данных вычисляет общее количество строк в разделе:

SELECT g.name, m.created_at,
       COUNT(*) OVER(PARTITION by g.id ORDER BY m.created_at) count,
       COUNT(*) OVER(PARTITION by g.id) total
FROM members m
INNER JOIN groups g on g.id = m.group_id

Примечание. Я подозрительно отношусь к использованию DISTINCT в предложении SELECT, поэтому я удалил его (редко имеет смысл использовать это вместе с оконными функциями, хотя есть крайние случаи) - вы можете добавить его обратно, если это необходимо.

0 голосов
/ 24 апреля 2020

Я бы написал это с явной агрегацией:

SELECT g.name, m.created_at,
       SUM(COUNT(*)) OVER (PARTITION BY g.id ORDER BY m.created_at) as count_on_day,
       SUM(COUNT(*)) OVER (PARTITION BY g.id) as count_for_group
FROM members m INNER JOIN
     groups g 
     ON g.id = m.group_id
GROUP BY g.name, m.created_at
...