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"
}
}
}
我试过的
我已经使用 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"
}
]
这里有两个可以让您接近的解决方案。
示例数据:
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')
我最基本的查询,当我只是从数据库中提取字段时,看起来像这样:
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"
}
}
}
我试过的
我已经使用 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"
}
]
这里有两个可以让您接近的解决方案。
示例数据:
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')