Как я могу получить несколько COUNT в одном запросе SQL с несколькими условиями WHERE? - PullRequest
0 голосов
/ 06 марта 2019

Мне нужно получить отчет об активности пользователей в веб-приложении.

Во-первых, у меня есть таблица, которая подсчитывает, сколько раз пользователь входит в наше приложение, и выглядит так:

user_activity
-----------------------------------------------------
| ID_login | Username | Date       | Hour     | ... |
|---------------------|------------|----------|-----|
|        1 | john     | 2019-03-01 | 08:49:24 | ... |
|        2 | john     | 2019-03-01 | 14:12:49 | ... |
|        3 | jane     | 2019-03-03 | 10:02:31 | ... |
|      ... | ...      | ...        | ...      | ... |
-----------------------------------------------------

То, что я хочу сделать, - это иметь отчет, который даст мне не только общую сумму входа в систему на пользователя за определенный период времени.Это я уже могу сделать.Я застреваю, когда пытаюсь получить отчет за каждый месяц предыдущего года, где месяцы находятся в отдельных столбцах.

Я бы хотел, чтобы таблица, сгенерированная моим запросом, выглядела так:

user_activity
--------------------------------------------------------
| Username | login_total | login_jan | login_feb | ... |
|------------------------|-----------|-----------|-----|
| john     |        4827 |       164 |       191 | ... |
| james    |        3866 |        92 |       144 | ... |
| jane     |        2979 |       104 |        92 | ... |
| ...      |         ... |       ... |       ... | ... |
--------------------------------------------------------

Итак, как вы можете видеть, я думал об использовании значения login_total для использования в ORDER BY.

Итак, вот что у меня есть на данный момент.

SELECT
    user_activity.Username,
    COUNT(user_activity.ID_login) AS login_total

FROM
    user_activity

WHERE
    user_activity.Date >= '2018-01-01'
    AND
    user_activity.Date <= '2018-12-31'

Как получить другой столбец с COUNT, но с другими критериями?Где я должен поставить эти критерии?Я пытался использовать операторы IF и HAVING, но это не сработало.

Я думал, что-то вроде этого ...?

SELECT
    user_activity.Username,
    COUNT(
        IF
            (user_activity.Date >= '2019-01-01'
            AND
            user_activity.Date <= '2019-01-31')
        user_activity.ID_login) 
        AS login_jan,

    COUNT(
        IF
            (user_activity.Date >= '2019-02-01'
            AND
            user_activity.Date <= '2019-02-28')
        user_activity.ID_login) 
        AS login_feb,
    ...

FROM
    user_activity

Кажется, тоже не работает... Что-то мне не хватает?

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

Вы пытаетесь создать таблицу PIVOT, которую вы можете сделать в MySQL, используя условное агрегирование. Обратите внимание, что вы можете упростить выражения, используя функции MONTH и YEAR:

SELECT u.Username,
       COUNT(*) AS login_total,
       SUM(MONTH(u.Date) = 1) AS login_jan,
       SUM(MONTH(u.Date) = 2) AS login_feb,
       ...
       SUM(MONTH(u.Date) = 12) AS login_dec
FROM user_activity u
WHERE YEAR(u.Date) = 2018
GROUP BY u.Username

Этот запрос также использует тот факт, что в числовом контексте MySQL обрабатывает логическое выражение как 1 (true) или 0 (false), что позволяет нам SUM эти значения.

2 голосов
/ 06 марта 2019

Мы можем выполнить условное агрегирование, что-то вроде этого:

SELECT ua.username
     , SUM( ua.date >= '2019-01-01' AND ua.date < '2019-02-01' ) AS login_jan
     , SUM( ua.date >= '2019-02-01' AND ua.date < '2019-03-01' ) AS login_feb
  FROM user_activity ua
 GROUP
    BY ua.username

При использовании сокращения MySQL выражение внутри агрегата SUM() будет оценено как 1, 0 или NULL.Мы можем использовать функцию MySQL IF () или более переносимое выражение ANSI SQL CASE

SELECT ua.username
     , SUM(IF( ua.date >= '2019-01-01' AND ua.date < '2019-02-01' ,1,0)) AS login_jan
     , SUM(IF( ua.date >= '2019-02-01' AND ua.date < '2019-03-01' ,1,0)) AS login_feb
  FROM user_activity ua
 GROUP
    BY ua.username

или

SELECT ua.username
     , SUM(CASE WHEN ua.date >= '2019-01-01' AND ua.date < '2019-02-01' THEN 1 ELSE 0 END) AS login_jan
     , SUM(CASE WHEN ua.date >= '2019-02-01' AND ua.date < '2019-03-01' THEN 1 ELSE 0 END) AS login_feb
  FROM user_activity ua
 GROUP
    BY ua.username
...