Как получить сумму данных из одной таблицы по типу и периоду времени из другой?

Рейтинг: 1Ответов: 1Опубликовано: 13.03.2023

Есть 2 таблицы. С текущими лимитами на кол-во прочтений по книге booksStats и таблица со временем, когда она была прочитана reads. При наличии прочтений у книги за всё время, но отсутствии прочтений за период времени в результатах выводится во всех столбцах null, хотя надо только у periodReads сделать значение равным именно 0, не null. Как это исправить?

Запрос, который сейчас есть:

SELECT readsLimit, usagePeriod, SUM(readsCounter) as periodReads
FROM booksStats
LEFT JOIN reads ON reads.bookId=booksStats.bookId
WHERE IF((reads.bookId IS NOT NULL), CASE 
    WHEN usagePeriod = 0 THEN (added BETWEEN UTC_TIMESTAMP() - INTERVAL 1 MONTH AND UTC_TIMESTAMP())
    WHEN usagePeriod = 1 THEN (added BETWEEN UTC_TIMESTAMP() - INTERVAL 7 DAY AND UTC_TIMESTAMP())
    WHEN usagePeriod = 2 THEN (added BETWEEN UTC_TIMESTAMP() - INTERVAL 1 DAY AND  UTC_TIMESTAMP())
    WHEN usagePeriod = 3 THEN (added BETWEEN UTC_TIMESTAMP() - INTERVAL 1 HOUR AND UTC_TIMESTAMP())
    ELSE added <= UTC_TIMESTAMP() END, TRUE)

Если у выбранной книги стоит ограничение на сутки (usagePeriod = 2), а в чтениях за этот период ничего нет, то выдаст:

readsLimit;usagePeriod;periodReads
null;null;null

А хотелось бы:

readsLimit;usagePeriod;periodReads
10000;2;0

Вот пример в mysql online, только предварительно надо убрать установку sql_mode=only_full_group_by.

Код CREATE:

CREATE TABLE `booksStats` (
  id INTEGER PRIMARY KEY,
  readsLimit INTEGER NOT NULL,
  usagePeriod INTEGER not null,
  bookId INTEGER not null
);
CREATE TABLE `reads` (
  id INTEGER PRIMARY KEY,
  added datetime NOT NULL,
  bookId INTEGER not null,
  readsCounter INTEGER not null
);

Ответы

▲ 0Принят

Надо было условия из where переместить на join. Однако мне до сих пор не понятно, почему при левом соединении, колонки левой таблицы были null, когда условие на промежуток не срабатывало. Должен же вернуться пустой запрос т.к. получилось что-то вроде where false.

Исправленный запрос:

SELECT readsLimit, usagePeriod, SUM(readsCounter) as periodReads
FROM booksStats
LEFT JOIN reads ON reads.bookId=booksStats.bookId AND IF((reads.bookId IS NOT NULL), CASE 
    WHEN usagePeriod = 0 THEN (added >= UTC_TIMESTAMP() - INTERVAL 1 MONTH)
    WHEN usagePeriod = 1 THEN (added >= UTC_TIMESTAMP() - INTERVAL 7 DAY)
    WHEN usagePeriod = 2 THEN (added >= UTC_TIMESTAMP() - INTERVAL 1 DAY)
    WHEN usagePeriod = 3 THEN (added >= UTC_TIMESTAMP() - INTERVAL 1 HOUR)
    ELSE added <= UTC_TIMESTAMP() END, TRUE)
WHERE booksStats.bookId = 5