Как перебрать и вернуть каждый доступный час дня в SQL? - PullRequest
0 голосов
/ 08 ноября 2019

Я пытаюсь запросить данные о времени открытых встреч из системы управления практикой и имею доступ только для чтения. Существует столбец для заблокированных слотов, который представляет время, доступное для бронирования, и столбец для забронированных слотов, который показывает, было ли забронировано время или нет. Каждый 5-минутный интервал в 24-часовом периоде представлен как 0 или 1. Доступное время будет представлено 1 в столбце заблокированных слотов и 0 в столбце забронированных слотов. Каков наилучший способ перебрать это и вернуть доступные даты и времени?

До сих пор я пытался создать операторы case, которые возвращают время в качестве заголовка и значение «OPEN», если час доступен, ноМне просто нужно возвращать каждую дату / время для каждого провайдера и местоположения, только если они доступны.

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

    Select
      Cast(vwApptSchedAvail.Available_Date As datetime) As [Date],
      vwApptSchedAvail.Location As [Location],
      vwApptSchedAvail.Department As [Department],
      vwApptSchedAvail.Resource As [Resource],
      Available_Days.Blocked_Slots1 + Available_Days.Blocked_Slots2 As [Blocked Slots],
      Available_Days.Booked_Slots1 + Available_Days.Booked_Slots2 As [Booked Slots]
    From
      PM.vwApptSchedAvail vwApptSchedAvail Inner Join
      PM.Available_Days Available_Days On vwApptSchedAvail.Available_Date =
        Available_Days.Available_Date And vwApptSchedAvail.Resource_ID =
        Available_Days.Resource_ID And vwApptSchedAvail.Scheduling_Department_ID =
        Available_Days.Scheduling_Department_ID And
        vwApptSchedAvail.Scheduling_Location_ID =
        Available_Days.Scheduling_Location_ID
    Where
      vwApptSchedAvail.Available_Date Between '2019-10-23' And '2019-10-23' And
      vwApptSchedAvail.Location = 'Location A' And
      vwApptSchedAvail.Department = 'OP' And
      vwApptSchedAvail.Booking_Factor > 0
    Group By
      Cast(vwApptSchedAvail.Available_Date As date),
      vwApptSchedAvail.Location, vwApptSchedAvail.Department,
      vwApptSchedAvail.Resource,
      vwApptSchedAvail.Booking_Factor, Available_Days.Blocked_Slots1,
      Available_Days.Blocked_Slots2, Available_Days.Booked_Slots1,
      Available_Days.Booked_Slots2

Мой запрос возвращает что-то вроде этого:

    +============+============+============+==============+==================================================================================================================================================================================================================================================================================================+==================================================================================================================================================================================================================================================================================================+
    |    Date    |  Location  | Department |   Resource   |                                                                                                                                          Blocked Slots                                                                                                                                           |                                                                                                                                           Booked Slots                                                                                                                                           |
    +============+============+============+==============+==================================================================================================================================================================================================================================================================================================+==================================================================================================================================================================================================================================================================================================+
    | 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 |
    +------------+------------+------------+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

Вот как возвращаются данные, когда я использовал операторы case, как упоминалось выше:

    +============+============+============+==============+=========+=========+=========+=========+=========+=========+=========+=========+=========+=========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+
    |    Date    |  Location  | Department |   Resource   | 0:00:00 | 1:00:00 | 2:00:00 | 3:00:00 | 4:00:00 | 5:00:00 | 6:00:00 | 7:00:00 | 8:00:00 | 9:00:00 | 10:00:00 | 11:00:00 | 12:00:00 | 13:00:00 | 14:00:00 | 15:00:00 | 16:00:00 | 17:00:00 | 18:00:00 | 19:00:00 | 20:00:00 | 21:00:00 | 22:00:00 | 23:00:00 |
    +============+============+============+==============+=========+=========+=========+=========+=========+=========+=========+=========+=========+=========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+==========+
    | 10/23/2019 | Location A | OP         |   Provider 2 |         |         |         |         |         |         |         |         |         |         | OPEN     |          |          |          |          | OPEN     |          |          |          |          |          |          |          |          |
    +------------+------------+------------+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+

Это лучше, чем0 и 1, но все еще не в том формате, в котором я нуждаюсь.

В конечном счете, я хотел бы получить что-то вроде этого:

    +==================+============+============+==============+
    |    Date/Time     |  Location  | Department |   Resource   |
    +==================+============+============+==============+
    | 10/23/19 5:00 PM | Location A | OP         |   Provider 1 |
    +------------------+------------+------------+--------------+
    | 10/23/19 6:00 PM | Location A | OP         |   Provider 1 |
    +------------------+------------+------------+--------------+
    | 10/23/19 7:00 PM | Location A | OP         |   Provider 1 |
    +------------------+------------+------------+--------------+
    | 10/23/19 4:00 PM | Location A | OP         |   Provider 2 |
    +------------------+------------+------------+--------------+
    | 10/23/19 5:00 PM | Location A | OP         |   Provider 2 |
    +------------------+------------+------------+--------------+
    | 10/23/19 7:00 PM | Location A | OP         |   Provider 2 |
    +------------------+------------+------------+--------------+

1 Ответ

0 голосов
/ 08 ноября 2019

Благодарим Вас за публикацию образцов данных в виде текста, чтобы мы могли легко использовать эти расходные материалы.

В этой проблеме есть два основных препятствия. Первая проблема - анализ этого кошмарного нити в нечто пригодное для использования. Самый простой способ справиться с этим - это счетный стол. Я создал один здесь как 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-промежутков и островков в последовательностях /

Первый взглядна этой логике разбора и пойми, что она делает. Тогда сделайте снимок в промежутках и островках. Я могу помочь с последним толчком, если вам это нужно, но вы узнаете эту технику намного лучше, если разберетесь с ней. Имейте в виду, что это нелегко и не для слабонервных. Но ужасная архитектура, с которой вы застряли, делает подобные вещи в миллион раз сложнее, чем нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...