Выбор значений в таблице, не относящихся к временному диапазону

#sql #sql-server

#sql #sql-сервер

Вопрос:

У меня есть две таблицы (упрощенная версия):

 create table Schedule(
Id int,
ScheduledData datetime,
UserId int)

create table User(
Id int,
Name varchar(50))
  

В первой таблице я храню все запланированные встречи, привязывая ее к пользователю.

Что я хочу, так это получить все свободное время, которое есть у пользователя. Это не обязательно должно быть очень подробно.

Например, если у пользователя не назначена встреча на 02.07.2014 утром (ранее 12:59:59), отобразите строку с именем пользователя и датой. То же самое, если у него есть свободный день.

Что я пробовал до сих пор, но у меня не получилось, так это создать временную таблицу и заполнить ее всеми днями месяца и всеми пользователями в моей базе данных. Это хорошо сработало при использовании CTE:

 create table #Temp(
StartData datetime,
EndDate datetim,
UserId int)
  

Затем я сделал это для отображения строк:

 select U.Name, X.ScheduledDate
from #Temp T
left outer join 
(select S.UserId
from Schedules S
where ScheduledData between @X and @Y) X on T.UserId = S.UserId
left outer join User U on T.UserId = U.Id
where S.ScheduledDate between T.StartDate and T.EndDate
  

Это не сработало хорошо, и я не могу в этом разобраться. Я боролся с этим весь день, и это лучшее, что у меня есть на данный момент.

Ответ №1:

Для решения проблемы могло бы потребоваться немного больше спецификаций:

  • Что означает строка в «Расписании»? Столбец ‘ScheduledData’ занимает всего один момент времени; это время начала собрания? Как долго длится собрание?
  • Что значит отображать «все свободное время пользователя»? Время — это непрерывная (ну, своего рода) величина. Как должен быть представлен результат?

Суть вашего примера, по-видимому, заключается в том, что при заданном интервале времени возвращайте значение true / false для определения того, произошла ли встреча за это время. Допустим, у вас есть таблица под названием «Пользователи», содержащая идентификатор каждого пользователя. Как насчет создания таблицы ‘time_segments’ с тремя столбцами ‘id’, ‘start_time’ и ‘end_time’; вы могли бы определить любой сегмент времени, который вы хотите, например, ваш блок ‘morning’, а затем извлекать свободное время с помощью чего-то вроде:

 select UserId,all_slots.id
from
( select
    TimeSegments.id, UserId
  from
    TimeSegments
    cross join Users ) all_slots
left outer join
( select
    TimeSegments.id, UserId
  from
    Schedule
    cross join TimeSegments
  where
    Schedule.datetime between TimeSegments.start_time and TimeSegments.end_time
) booked using(id, UserId)
where
  booked.UserID is null