SQL Сервер - нормализовать данные о рабочих часах в JSON объект - PullRequest
1 голос
/ 17 июня 2020

Мой самый простой c запрос, когда я просто извлекаю поля из базы данных, выглядит примерно так:

SELECT DISTINCT  
    [BranchCode]
     ,[Weekday]
     ,[OpenTime]
     ,[CloseTime]
FROM [Departments]
WHERE [BranchCode] like '%1001.0000%'

И он дает мне такой результат:

BranchCode  Weekday     OpenTime    CloseTime
=============================================
1001.0000   Friday      06:00       21:00
1001.0000   Monday      06:00       21:00
1001.0000   Saturday    NULL        NULL
1001.0000   Sunday      NULL        NULL
1001.0000   Thursday    08:00       17:00
1001.0000   Tuesday     08:00       17:00
1001.0000   Wednesday   08:00       17:00

То, что я пытаюсь достичь

, - это JSON похожий на этот результат для каждого BranchCode

"1001.0000": {
    "HoursOfOpertion": {
        "Monday": {
            "OpenTime": "06:00",
            "CloseTime": "21:00"
        },
        "Tuesday": {
            "OpenTime": "06:00",
            "CloseTime": "21:00"
        },
        "Wednesday": {
            "OpenTime": "06:00",
            "CloseTime": "21:00"
        },
        "Thursday": {
            "OpenTime": "06:00",
            "CloseTime": "21:00"
        },
        "Friday": {
            "OpenTime": "08:00",
            "CloseTime": "17:00"
        },
        "Saturday": {
            "OpenTime": "NULL",
            "CloseTime": "NULL"
        },
        "Sunday": {
            "OpenTime": "NULL",
            "CloseTime": "NULL"
        }
    }
}

То, что я пробовал

Я зашел в тупик, используя PIVOT и JOIN, я чувствую, что близок, но все еще не добираюсь даже близко к тому, что мне нужно.

SELECT distinct
        [CloseTime]
        ,[Sunday]
        ,[Monday]
        ,[Tuesday]
        ,[Wednesday]
        ,[Thursday]
        ,[Friday]
        ,[Saturday]
FROM [Branches] as br
LEFT JOIN(
    SELECT 
        * FROM (
        SELECT DISTINCT
            [Weekday] as [WD]
            ,[OpenTime]
            ,[CloseTime]
            ,[Closed]
            ,[BranchCode]
        FROM [Departments]

    ) AS SRC PIVOT (
        MAX([OpenTime])
            FOR [WD] IN (
        [Sunday]
        ,[Monday]
        ,[Tuesday]
        ,[Wednesday]
        ,[Thursday]
        ,[Friday]
        ,[Saturday]
        )
    ) as PVT
) p
on p.[BranchCode] = br.[BranchCode]
where br.[BranchCode] like '%1001.0000%'
FOR JSON PATH

Это дает мне что-то вроде этого:

[
    {
        "CloseTime":"1700",
        "Monday":"0800"
    },
    {
        "CloseTime":"1700",
        "Tuesday":"0800"
    },
    {
        "CloseTime":"1700",
        "Wednesday":"0800"
    },
    {
        "CloseTime":"1700",
        "Thursday":"0800"
    },
    {
        "CloseTime":"1700",
        "Friday":"0800"
    },
    {
        "CloseTime":"1800",
        "Saturday":"0800"
    }
]

1 Ответ

1 голос
/ 18 июня 2020

Вот два решения, которые могут вам помочь.

Примеры данных:

DECLARE @data TABLE
(
    BranchCode NVARCHAR(100)
    ,WeekDay NVARCHAR(100)
    ,OpenTime NVARCHAR(100)
    ,CloseTime NVARCHAR(100)
)

INSERT INTO @data
VALUES
('1001.0000', 'Friday', '06:00', '21:00')
,('1001.0000', 'Monday', '06:00', '21:00')
,('1001.0000', 'Saturday', NULL, NULL)
,('1001.0000', 'Sunday', NULL, NULL)
,('1001.0000', 'Thursday', '08:00', '17:00')
,('1001.0000', 'Tuesday', '08:00', '17:00')
,('1001.0000', 'Wednesday', '08:00', '17:00')

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

select BranchCode,
    (SELECT 
        WeekDay
        ,OpenTime
        ,CloseTime
     FROM @data dInner
     WHERE dInner.BranchCode = dOuter.BranchCode
     FOR JSON PATH
     ) as [HoursOfOperation]
FROM @data dOuter
FOR JSON PATH, INCLUDE_NULL_VALUES, ROOT('Branches')

Второй менее динамичный c но ближе к вашему примеру. Поскольку SQL использует имя таблицы в качестве имени элемента, трудно предоставить именованный элемент для каждой ветви. Мы можем сделать это для будних дней, потому что они являются известной константой. Таким образом, вы просто получите массив объектов ветки со свойством кода ветки и часами работы. Для этого решения также можно использовать образцы данных.

select DISTINCT BranchCode,
    (SELECT
        OpenTime
        ,CloseTime
     FROM @data dInner
     WHERE dInner.BranchCode = dOuter.BranchCode and dInner.[WeekDay] = 'Sunday'
     FOR JSON PATH, INCLUDE_NULL_VALUES
     ) as [HoursOfOperation.Sunday]
     ,(SELECT
        OpenTime
        ,CloseTime
     FROM @data dInner
     WHERE dInner.BranchCode = dOuter.BranchCode and dInner.[WeekDay] = 'Monday'
     FOR JSON PATH, INCLUDE_NULL_VALUES
     ) as [HoursOfOperation.Monday]
     ,(SELECT
        OpenTime
        ,CloseTime
     FROM @data dInner
     WHERE dInner.BranchCode = dOuter.BranchCode and dInner.[WeekDay] = 'Tuesday'
     FOR JSON PATH, INCLUDE_NULL_VALUES
     ) as [HoursOfOperation.Tuesday]
     ,(SELECT
        OpenTime
        ,CloseTime
     FROM @data dInner
     WHERE dInner.BranchCode = dOuter.BranchCode and dInner.[WeekDay] = 'Wednesday'
     FOR JSON PATH, INCLUDE_NULL_VALUES
     ) as [HoursOfOperation.Wednesday]
     ,(SELECT
        OpenTime
        ,CloseTime
     FROM @data dInner
     WHERE dInner.BranchCode = dOuter.BranchCode and dInner.[WeekDay] = 'Thursday'
     FOR JSON PATH, INCLUDE_NULL_VALUES
     ) as [HoursOfOperation.Thursday]
     ,(SELECT
        OpenTime
        ,CloseTime
     FROM @data dInner
     WHERE dInner.BranchCode = dOuter.BranchCode and dInner.[WeekDay] = 'Friday'
     FOR JSON PATH, INCLUDE_NULL_VALUES
     ) as [HoursOfOperation.Friday]
     ,(SELECT
        OpenTime
        ,CloseTime
     FROM @data dInner
     WHERE dInner.BranchCode = dOuter.BranchCode and dInner.[WeekDay] = 'Saturday'
     FOR JSON PATH, INCLUDE_NULL_VALUES
     ) as [HoursOfOperation.Saturday]
FROM @data dOuter
FOR JSON PATH, INCLUDE_NULL_VALUES, ROOT('Branches')
...