#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