Как включить результаты подсчета SQL, если count = 0? - PullRequest
0 голосов
/ 04 ноября 2018

У меня есть таблица с оценками (1-6) примерно так:

mysql> SELECT two FROM data  WHERE date >= '2018-10-23 00:00:00' AND date < '2018-10-23 23:59:59';
+------+
| two  |
+------+
| 5    |
| 1    |
| 1    |
| 2    |
| 1    |
| 2    |
| 2    |
| 1    |
| 1    |
+------+
9 rows in set (0.00 sec)

Мне нужно количество экземпляров каждого сорта, например:

mysql> SELECT two, COUNT(1) as count  from data lookup where date >= '2018-10-23 00:00:00' AND date < '2018-10-23 23:59:59' GROUP BY two;
+------+-------+
| two  | count |
+------+-------+
| 1    |     5 |
| 2    |     3 |
| 5    |     1 |
+------+-------+
3 rows in set (0.00 sec)

НО я хочу включить оценки, даже если они не существуют в выборе, например:

+------+-------+
| two  | count |
+------+-------+
| 1    |     5 |
| 2    |     3 |
| 3    |     0 |
| 4    |     0 |
| 5    |     1 |
| 6    |     0 |
+------+-------+
6 rows in set (0.00 sec)

Я видел решения с использованием LEFT JOIN и таблиц поиска, но они слишком сложны, чтобы моя голова для начинающих SQL могла их обернуть.

Я составил справочную таблицу (noten = grades):

mysql> SELECT * from lookup;
+-------+
| noten |
+-------+
|     1 |
|     2 |
|     3 |
|     4 |
|     5 |
|     6 |
+-------+
6 rows in set (0.00 sec)

Но я не могу понять это правильно ...

mysql> SELECT two, COUNT(1) as count  FROM data LEFT JOIN lookup on two=lookup.noten  WHERE date >= '2018-10-23 00:00:
+------+-------+
| two  | count |
+------+-------+
| 1    |     5 |
| 2    |     3 |
| 5    |     1 |
+------+-------+
3 rows in set (0.00 sec)

Ваша помощь будет принята с благодарностью !!!

Ответы [ 4 ]

0 голосов
/ 04 ноября 2018

Публикация слегка измененной версии @ gordon-linoff, которая добилась цели. Спасибо всем!

SELECT lookup.noten, COUNT(data.two) as count 
FROM lookup LEFT JOIN
data ON data.two = lookup.noten AND 
data.date >= '2018-10-23' AND data.date < '2018-10-24' 
GROUP BY lookup.noten 
ORDER BY lookup.noten;
0 голосов
/ 04 ноября 2018

Вы бы использовали left join. Хитрость заключается в том, чтобы правильно определить условия count() и дату. Я бы написал это как:

SELECT l.noten, COUNT(d.noten) as count
FROM lookup l LEFT JOIN
     data d
     ON d.noten = l.noten AND
        d.date >= '2018-10-23' AND d.date < '2018-10-24'
GROUP BY l.noten
ORDER BY l.noten;

В частности, обратите внимание, что логике даты не нужны компоненты времени, чтобы выполнить то, что вы хотите.

0 голосов
/ 04 ноября 2018

Один вариант будет использовать INFORMATION_SCHEMA.CHARACTER_SETS на cross/left joins рекурсивно как:

select q.rn as two, 
       count(coalesce(t.two)) as count
  from
    (  
    select @rownum := @rownum + 1 rn
      from (select @rownum := 0) t
      cross join INFORMATION_SCHEMA.CHARACTER_SETS 
     limit 6 
    ) q 
  left join data t
    on ( t.two = q.rn and date >= '2018-10-23 00:00:00' and date < '2018-10-23 23:59:59' )
 group by rn    
 order by rn;

 two    count
  1       5
  2       3
  3       0
  4       0
  5       1
  6       0

Rextester Demo

0 голосов
/ 04 ноября 2018
  • Вместо создания фактической таблицы поиска вы можете эмулировать ее в самом запросе, используя Union All, и использовать ее как Производная таблица .
  • Вам нужно будет сделать Left Join из этой таблицы поиска в таблицу data.
  • Обратите внимание , что при использовании Left Join (s) любые условия в таблицах справа должны указываться в предложении On вместо Where. Если они указаны в Where, это ограничит ваши результаты и фактически сделает его только внутренним.

Попробуйте следующее:

SELECT agl.grade, COUNT(d.two) FROM 
(SELECT 1 AS grade UNION ALL 
 SELECT 2 UNION ALL
 SELECT 3 UNION ALL
 SELECT 4 UNION ALL
 SELECT 5 UNION ALL
 SELECT 6) AS agl
LEFT JOIN data AS d ON d.two = agl.grade AND 
                  d.date >= '2018-10-23 00:00:00' AND 
                  d.date < '2018-10-23 23:59:59' 
GROUP BY agl.grade
...