мы могли бы использовать шаблон антисоединения
кратко ... запрос, чтобы вернуть все даты и пользователей, с внешним объединением, чтобы включить совпадающие строки из постов, а затем исключить все строки, у которых была совпадающая строка из сообщения, оставляя строки, у которых не было соответствующей строки в сообщениях
В качестве отправной точки мы можем получить декартово произведение (cross join
) всех дат со всеми пользователями.
SELECT d.dt
, u.user_name
FROM ( SELECT '2018-01-01' + INTERVAL 0 DAY AS dt
UNION ALL SELECT '2018-01-01' + INTERVAL 1 DAY
UNION ALL SELECT '2018-01-01' + INTERVAL 2 DAY
UNION ALL SELECT '2018-01-01' + INTERVAL 3 DAY
) d
CROSS
JOIN `USERS` u
ORDER
BY d.dt
, u.user_name
(Чтобы вернуть строки из запроса, нам нужен источник для этих строк. Мы не можем получить «пропущенные» строки, возвращаемые только из таблицы POSTS
. Нам нужен полный набор строк, затем мы можем сравнить с содержимое таблицы POSTS
.)
Мы можем добавить внешнее соединение, чтобы идентифицировать совпадающие строки, а затем исключить строки, у которых есть совпадение.
SELECT d.dt
, u.user_name
FROM ( SELECT '2018-01-01' + INTERVAL 0 DAY AS dt
UNION ALL SELECT '2018-01-01' + INTERVAL 1 DAY
UNION ALL SELECT '2018-01-01' + INTERVAL 2 DAY
UNION ALL SELECT '2018-01-01' + INTERVAL 3 DAY
) d
CROSS
JOIN `USERS` u
-- anti-join, exclude rows that have a matching row in posts
LEFT
JOIN `POSTS` p
ON p.user_name = u.user_name
AND p.dt = d.dt
WHERE p.dt IS NULL
ORDER
BY d.dt
, u.user_name
Пример запроса возвращает каждую отдельную дату вместе с пользователями, у которых не было публикации на эту отдельную дату. Это удовлетворяет одной возможной интерпретации довольно расплывчатой спецификации "кто не публиковал от ... до ... и сгруппировал ее по датам"
Чтобы этот запрос вернул ожидаемые результаты, мы могли бы создать пример данных :
USERS
user_name
---------
Ana
Charlie
John
Lucas
Sandra
и
POSTS
user_name dt
--------- ----------
Charlie 2020-01-01
Lucas 2020-01-01
Charlie 2020-01-02
John 2020-01-02
Lucas 2020-01-02
Ana 2020-01-03
Sandra 2020-01-03
John 2020-01-04
Lucas 2020-01-04
Sandra 2020-01-04
Мы можем использовать NOT EXISTS с коррелированным подзапросом вместо анти-объединения, чтобы возвращать эквивалентные результаты ...
SELECT d.dt
, u.user_name
FROM ( SELECT '2018-01-01' + INTERVAL 0 DAY AS dt
UNION ALL SELECT '2018-01-01' + INTERVAL 1 DAY
UNION ALL SELECT '2018-01-01' + INTERVAL 2 DAY
UNION ALL SELECT '2018-01-01' + INTERVAL 3 DAY
) d
CROSS
JOIN `USERS` u
WHERE NOT EXISTS
( SELECT 1
FROM `POSTS` p
WHERE p.user_name = u.user_name
AND p.dt = d.dt
)
ORDER
BY d.dt
, u.user_name