SQL 服务器 - 将营业时间数据规范化为 JSON 对象

SQL Server - Normalize Business Hours Data into JSON Object

我最基本的查询,当我只是从数据库中提取字段时,看起来像这样:

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

我想要实现的目标

与每个 BranchCode

的结果 JSON 相似
"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"
        }
    }
}

我试过的

我已经使用 PIVOTJOIN 进入了死胡同,我觉得我已经接近了,但我仍然没有得到任何接近我需要的东西。

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"
    }
]

这里有两个可以让您接近的解决方案。

示例数据:

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')

第一种方法更像是一种动态方法,但与您的预期结果有些偏差,但需要的代码较少。

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')

第二个不太动态,但更接近您的示例。因为 SQL 使用 table 名称作为元素名称,所以很难为每个分支提供命名元素。我们可以在工作日执行此操作,因为它们是已知常数。所以基本上你最终会得到一个带有分支代码 属性 和营业时间的分支对象数组。示例数据也可用于此解决方案。

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')