Первый запрос выбирает всех пользователей, у которых нет регистрации между @start и @end:
SELECT users.userName
FROM users
LEFT JOIN timesheets
ON timesheets.timesheetForUser = users.userID
AND timesheets.timesheetForDate BETWEEN @start AND @end
WHERE timesheets.timesheetForUser IS NULL
Этот запрос выбирает всех пользователей, которые пропали без вести в какие дни и в какие дни они пропускают (как вы просили в комментарии к вашему вопросу):
SELECT dates.timesheetForDate, users.userName
FROM (SELECT DISTINCT timesheetForDate FROM timesheets) AS dates
CROSS JOIN users
LEFT JOIN timesheets
ON timesheets.timesheetForUser = users.userID
AND dates.timesheetForDate = timesheets.timesheetForDate
WHERE timesheets.timesheetForUser IS NULL
Тестовая кровать:
CREATE TABLE timesheets (timesheetForUser int, timesheetForDate datetime);
INSERT INTO timesheets (timesheetForUser, timesheetForDate) VALUES
(1, '2010-01-01'),
(2, '2010-01-01'),
(3, '2010-01-01'),
(1, '2010-01-02'),
(3, '2010-01-02'),
(2, '2010-01-03'),
(2, '2010-01-04'),
(3, '2010-01-04');
CREATE TABLE users (userId int, userName nvarchar(100));
INSERT INTO users (userId, userName) VALUES
(1, 'Foo'),
(2, 'Bar'),
(3, 'Baz');
Вывод из второго запроса с использованием тестового стенда:
'2010-01-02 00:00:00', 'Bar'
'2010-01-03 00:00:00', 'Foo'
'2010-01-03 00:00:00', 'Baz'
'2010-01-04 00:00:00', 'Foo'
Если вы хотите, вы также можете создать второй запрос как представление и запросить его следующим образом:
SELECT * FROM ViewMissingRegistrations
WHERE timesheetForDate BETWEEN @start AND @end