SQL Null как 0 с левым соединением?

0

проблема

У меня есть таблица журналов, в которой пользователи вводят количество часов, потраченных на проект. (Он используется для графиков и таблиц данных в приложении). Я также создал таблицу "calendar", чтобы я мог оставить даты присоединения и заполнить "пустые" даты нулем. Однако, проведя некоторое время, я не смог найти способ сделать это...

Таблица 1: Журналы

id | hoursSpent | logDate 
1    5            2018-08-05
2    1            2018-08-07
3    3            2018-08-10

Таблица 2: Календарь

id         | db_date
20180807     2018-08-07
20180808     2018-08-08
20180809     2018-08-09
201808010    2018-08-10
etc...

Желаемый результат

db_date      | hoursSpent
2018-08-05     5
2018-08-06     0
2018-08-07     1
2018-08-08     0
2018-08-09     0
2018-08-10     3

Код, используемый до сих пор (не работает точно...)

SELECT hoursSpent, db_date
FROM logs LEFT JOIN calendar ON db_date
WHERE db_date BETWEEN '2018-08-10' AND '2018-08-01'
GROUP BY db_date
Теги:

3 ответа

0

Таблица, содержащая все необходимые строки (Calendar), должна быть слева от LEFT JOIN, таблица с отсутствующими записями (Logs) справа. Кроме того, вы можете сохранить порядок таблиц и вместо этого использовать RIGHT JOIN.

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

Для полного предложения ON требуется сравнение.

Диапазон, указанный в состоянии BETWEEN должен быть в порядке возрастания.

Предложение GROUP BY требует применения агрегатной функции ко всем негрупповым выражениям в SELECT -list. Здесь подходит функция SUM. Поскольку функция SUM возвращает NULL если нет совпадающих записей, мы применяем функцию COALESCE для преобразования их в 0 с.

SELECT
    c.db_date, COALESCE(SUM(l.hoursSpent), 0) AS hoursSpent
FROM
    Calendar c
    LEFT JOIN Logs l
        ON c.db_date = l.logDate
WHERE
    c.db_date BETWEEN '2018-08-01' AND '2018-08-10'        
GROUP BY
    c.db_date;

См. SQL-скрипт: http://sqlfiddle.com/#!9/d28de9c/3/0

0

Правильное использование LEFT JOIN. Остальная часть запроса нуждается в очистке:

SELECT c.db_date, COALESCE(l.hoursSpent, 0) as hoursSpent
FROM calendar c LEFT JOIN
     logs l
     ON c.db_date = l.logdate
WHERE c.db_date BETWEEN '2018-08-01' AND '2018-08-10';

Заметки:

  • Вы хотите, чтобы все строки были из calendar, поэтому это должна быть первая таблица в LEFT JOIN.
  • Вам нужно действует ON условия, соединяющих две таблицы.
  • BETWEEN требует, чтобы операнды были в порядке, поэтому малый до AND и больше после.
  • GROUP BY кажется ненужным.
    • COALESCE() фактически генерирует значение 0.
  • В запросе с более чем одной ссылкой на таблицу укажите все имена столбцов.
  • 0
    ОПИСАНИЕ ЛЕВОГО СОЕДИНЕНИЯ не является правильным. Это неправильный путь. logs LEFT JOIN calendar вместо calendar LEFT JOIN logs .
  • 0
    @ OlivierJacot-Descombes. , , Ответ объясняет это.
Показать ещё 1 комментарий
0

Ваш порядок соединения неверен, calendar должен быть слева, так как все его строки должны быть включены независимо от соответствующей строки из logs. Чтобы преобразовать NULL в 0 используйте coalesce(). И если вы GROUP BY по дате, вы должны применить функцию агрегации на hoursspent. Думаю, вам нужна sum().

SELECT c.db_date,
       sum(coalesce(l.hoursspent, 0)) hoursspent
       FROM calendar c
            LEFT JOIN logs l
                      ON l.logdate = c.db_date
       WHERE c.db_date BETWEEN '2018-08-10'
                               AND '2018-08-01'
       GROUP BY c.db_date;

Здесь вы также можете опустить coalesce() поскольку MySQL sum() обрабатывает NULL как 0 любом случае.

Но в образцовых данных предполагается, что вам может вообще не понадобиться GROUP BY, если в течение одного дня имеется не более одной записи журнала.

SELECT c.db_date,
       coalesce(l.hoursspent, 0) hoursspent
       FROM calendar c
            LEFT JOIN logs l
                      ON l.logdate = c.db_date
       WHERE c.db_date BETWEEN '2018-08-10'
                               AND '2018-08-01';

Ещё вопросы

Сообщество Overcoder
Наверх
Меню