Multiple COUNT() in a single query

Asked

Viewed 96 times

0

Good morning, I have the following table:

+------------+--------------+------+-----+----------------+
| Field      | Type         | Null | Key | Extra          |
+------------+--------------+------+-----+----------------+
| idAcesso   | int(11)      | NO   | PRI | auto_increment |
| dataAcesso | date         | NO   |     |                |
| contato    | tinyint(1)   | YES  |     |                |
+------------+--------------+------+-----+----------------+

Her goal is to know how many people, from those who accessed a given page, came in contact. There are two contact forms on the page and, the contact column, receives the ID of the form used or the NULL value if you have not contacted.

I need to return the total of lines that were made contact or not grouped for days. More or less this:

+------------+--------------+---------------+------------+
| dataAcesso | totalAcessos | totalContatos | semContato |
+------------+--------------+---------------+------------+
| 2019-09-28 |           98 |            98 |         98 |
| 2019-09-29 |          114 |           114 |        114 |
| 2019-09-30 |          197 |           197 |        197 |
| 2019-10-01 |          185 |           185 |        185 |
| 2019-10-02 |          163 |           163 |        163 |
| 2019-10-03 |          167 |           167 |        167 |
| 2019-10-04 |           93 |            93 |         93 |
| 2019-10-05 |          102 |           102 |        102 |
| 2019-10-06 |          154 |           154 |        154 |
| 2019-10-07 |          295 |           295 |        295 |
+------------+--------------+---------------+------------+

The problem is that these values do not match, the 3 totals have different values and the totalAccesss should be the sum of the other totals.

I can get the correct values with 3 different Sqls but I would like to know if there is a way to do these queries correctly using just one query.

What I’m trying to:

SELECT
    dataAcesso,
    COUNT( idAcesso ) AS totalAcessos,
    COUNT( !ISNULL( contato ) ) AS totalContatos,
    COUNT( ISNULL( contato ) ) AS semContato
FROM
    acessos
GROUP BY
    dataAcesso

Any hint on how I can make this query?

Thank you.


EDIT

An example of how lines can be filled:

+----------+------------+---------+
| idAcesso | dataAcesso | contato |
+----------+------------+---------+
|        1 | 2019-09-28 |       1 |
|        2 | 2019-09-28 |       2 |
|        3 | 2019-09-28 |       2 |
|        4 | 2019-09-28 |    NULL |
|        5 | 2019-09-28 |    NULL |
|        6 | 2019-09-28 |    NULL |
|        7 | 2019-09-28 |    NULL |
|        8 | 2019-09-28 |    NULL |
|        9 | 2019-09-28 |    NULL |
|       10 | 2019-09-28 |    NULL |
|       11 | 2019-09-28 |    NULL |
|       12 | 2019-09-28 |    NULL |
|       13 | 2019-09-28 |    NULL |
|       14 | 2019-09-28 |    NULL |
|       15 | 2019-09-28 |    NULL |
|       16 | 2019-09-28 |    NULL |
|       17 | 2019-09-28 |    NULL |
|       18 | 2019-09-28 |       1 |
|       19 | 2019-09-28 |       1 |
|       20 | 2019-09-28 |       1 |
+----------+------------+---------+

Ricardo Pontual’s answer eventually led me to the solution, since I did not know that COUNT does not count null values:

SELECT
    dataAcesso,
    COUNT( idAcesso ) AS totalAcessos,
    COUNT( contato ) AS totalContatos,
    COUNT( IF(contato > 0, NULL, 1) ) AS semContato
FROM
    acessos
GROUP BY
    dataAcesso

1 answer

1


This happens because the COUNT does not count null values, you need a treatment:

SELECT
    dataAcesso,
    COUNT( idAcesso ) AS totalAcessos,
    COUNT( contato ) AS totalContatos,
    COUNT( NULLIF(contato, 1) ) AS semContato
FROM
    acessos
GROUP BY
    dataAcesso

Basically, the NULLIF(contato, 1) converts null and 1, contact 1 for each null

  • Thus the semContato will not return 0 since in the negative case the value returned will be the one of the first expression that will be NULL?

  • Did not return 0, but the values still do not match 2019-09-28 | totalAcessos: 20 | totalContatos: 6 | semContato: 2. With this it is already possible to do what I wanted. The totalAccesss and totalContacts are with the correct values so I could simply do totalAcessos - totalContatos to get the semContact. I will update the question with the filled table.

  • NULLIF is returning NULL when the value is 1, so it ends up counting the contacts in the id 2 form when it should actually count the total of NULL.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.