Благодарим Вас за публикацию образцов данных в виде текста, чтобы мы могли легко использовать эти расходные материалы.
В этой проблеме есть два основных препятствия. Первая проблема - анализ этого кошмарного нити в нечто пригодное для использования. Самый простой способ справиться с этим - это счетный стол. Я создал один здесь как cte. Наличие постоянной индексированной таблицы должно обеспечить небольшое повышение производительности, но не так много. Используя таблицу подсчета, вот как я бы выполнил первый шаг.
declare @Something table
(
ApptDate datetime
, LocationA varchar(20)
, OP char(2)
, Provider varchar(20)
, BlockedSlots varchar(500)
, BookedSlots varchar(500)
)
insert @Something values
('10/23/2019'
, 'Location A'
, 'OP'
, 'Provider 1'
, '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
, '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
)
,('10/23/2019'
, 'Location A'
, 'OP'
, 'Provider 2'
, '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000'
, '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111000000000000111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000'
)
,('10/23/2019'
, 'Location A'
, 'OP'
, 'Provider 3'
, '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111000000000000111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
, '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111000000000000000000000000111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
)
,('10/23/2019'
, 'Location A'
, 'OP'
, 'Provider 4'
, '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
, '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111110000222222222222111111112222111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
)
;
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a cross join E1 b cross join E1 c), --this is enough for 1,000 rows. Way more than we need here
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)
select s.ApptDate
, s.LocationA
, s.OP
, s.Provider
, TimeIsBlocked = substring(s.BlockedSlots, t.N, 1)
, BlockStartTime = dateadd(minute, 5 * (t.N - 1), ApptDate)
, BlockEndTime = dateadd(minute, (5 * (t.N - 1)) + 5, ApptDate)
, TimeIsBooked = substring(s.BookedSlots, t.N, 1)
from @Something s
join cteTally t on t.N <= 288 --the number of 5 minute time slots in a 24 hour period
order by s.Provider
, t.N
Это вернет 288 строк на строку данных примера (ваш основной запрос). Один на каждые пять минут. Он также вернет время начала и окончания этого слота, а также, если это время заблокировано и / или забронировано. Отсюда вам нужно выделить действительные доступные временные интервалы, используя подходы с пропусками и островами. На этот вопрос отвечали сотни и сотни раз. Лучшая статья о том, как справиться с этой проблемой, написана в конце великих лагерей Дуэйна. https://www.red -gate.com / simple-talk / sql / t-sql-программирования / sql-of-промежутков и островков в последовательностях /
Первый взглядна этой логике разбора и пойми, что она делает. Тогда сделайте снимок в промежутках и островках. Я могу помочь с последним толчком, если вам это нужно, но вы узнаете эту технику намного лучше, если разберетесь с ней. Имейте в виду, что это нелегко и не для слабонервных. Но ужасная архитектура, с которой вы застряли, делает подобные вещи в миллион раз сложнее, чем нужно.