SQL to JSON-将结果分组为JSON数组

时间:2019-02-13 12:12:24

标签: sql arrays json sql-server-2017

我正在尝试提出一种SQL解决方案,以安排输出以匹配预期的JSON格式。

我有一些简单的SQL来突出显示问题的出处;

SELECT TOP 1 'Surname' AS 'name.family'
,'Forename, Middle Name' AS 'name.given'
,'Title' AS 'name.prefix'
,getDATE() AS 'birthdate'
,'F' AS 'gender'
,'Yes' AS 'active'
,'work' AS 'telecom.use'
,'phone' AS 'telecom.system'
,'12344556' AS 'telecom.value'
FROM tblCustomer
FOR json path

哪个将以JSON的形式返回

[
{
    "name": {
        "family": "Surname",
        "given": "Forename, Middle Name",
        "prefix": "Title"
    },
    "birthdate": "2019-02-13T12:06:45.490",
    "gender": "F",
    "active": "Yes",
    "telecom": {
        "use": "work",
        "system": "phone",
        "value": "12344556"
    }
}
]

我需要在“ telecome”数组中添加额外的对象,以使其显示为

[
{
    "name": {
        "family": "Surname",
        "given": "Forename, Middle Name",
        "prefix": "Title"
    },
    "birthdate": "2019-02-13T12:06:45.490",
    "gender": "F",
    "active": "Yes",
    "telecom": {
        "use": "work",
        "system": "phone",
        "value": "12344556"
    },
    {
        "use": "work",
        "system": "home",
        "value": "12344556"
    },
}
]

我错误地认为我可以继续添加如下所示的SQL;

SELECT TOP 1 'Surname' AS 'name.family'
,'Forename, Middle Name' AS 'name.given'
,'Title' AS 'name.prefix'
,getDATE() AS 'birthdate'
,'F' AS 'gender'
,'Yes' AS 'active'
,'work' AS 'telecom.use'
,'phone' AS 'telecom.system'
,'12344556' AS 'telecom.value'
,'home' AS 'telecom.use'
FROM tblCustomer
FOR json path

但是它将按照我的命名缩进嵌套项目;

  

由于以下原因,无法在JSON输出中生成属性“ telecom.use”   与另一个列名或别名冲突。使用不同的名称和   SELECT列表中每一列的别名。

是否可以使用SQL处理这种嵌套,还是需要为JSON查询创建单独的并将其合并?

谢谢

  

使用@@ Version Microsoft SQL Server 2017(RTM)-14.0.1000.169(X64)   2017年8月22日17:04:49版权所有(C)2017 Microsoft Corporation   Windows Server 2012 R2 Datacenter 6.3上的Express Edition(64位)    (内部版本9600:)(管理程序)

对问题进行小的编辑以使用动态值而不是强制静态成员。

SELECT TOP 1 'Surname' AS 'name.family'
    ,'Forename, Middle Name' AS 'name.given'
    ,'Title' AS 'name.prefix'
    ,getDATE() AS 'birthdate'
    ,'F' AS 'gender'
    ,'Yes' AS 'active'
    ,'work' AS 'telecom.use'
    ,'phone' AS 'telecom.system'
    ,customerWorkTelephone AS 'telecom.value'
    ,'home' AS 'telecom.use'
    ,'phone' AS 'telecom.system'
    ,customerHomeTelephone AS 'telecom.value'
FROM tblCustomer
FOR json path

“值”项将从tblCustomer表中的列中获取。我试图在下面的响应中取得成功,但在子查询中无法获得正确的逻辑。

再次感谢

进一步编辑

我有一些SQL可以给我期望的输出,但是我不确定它可能是最好的,我的方法是否不是最优方法?

SELECT TOP 1 [name.family] = 'Surname'
,[name.given] = 'Forename, Middle Name'
,[name.prefix] = 'Title'
,[birthdate] = GETDATE()
,[gender] = 'F'
,[active] = 'Yes'
,[telecom] = (
    SELECT [use] = V.used
        ,[system] = 'phone'
        ,[value] = CASE V.used
            WHEN 'work'
                THEN cu.customerWorkTelephone
            WHEN 'home'
                THEN cu.customerHomeTelephone
            when 'mobile'
                then cu.customerMobileTelephone
            END
    FROM (
        VALUES ('work')
            ,('home')
            ,('mobile')
        ) AS V(used)

    FOR json path
    )
FROM tblCustomer cu
FOR JSON PATH

2 个答案:

答案 0 :(得分:1)

使用带有一些硬编码行的子选择:

SELECT TOP 1 
    'Surname' AS 'name.family'
    ,'Forename, Middle Name' AS 'name.given'
    ,'Title' AS 'name.prefix'
    ,getDATE() AS 'birthdate'
    ,'F' AS 'gender'
    ,'Yes' AS 'active'
    ,'telecom' = (
            SELECT
                'work' AS 'use'
                ,V.system AS 'system'
                ,'12344556' AS 'value'
            FROM
                (VALUES 
                    ('phone'),
                    ('home')) AS V(system)
            FOR JSON PATH)
FROM tblCustomer
FOR JSON PATH

请注意,子查询中缺少telecom.前缀。

结果(没有表格参考):

[
    {
        "name": {
            "family": "Surname",
            "given": "Forename, Middle Name",
            "prefix": "Title"
        },
        "birthdate": "2019-02-13T12:53:08.400",
        "gender": "F",
        "active": "Yes",
        "telecom": [
            {
                "use": "work",
                "system": "phone",
                "value": "12344556"
            },
            {
                "use": "work",
                "system": "home",
                "value": "12344556"
            }
        ]
    }
]

PD :特别是对于SQL Server,我发现使用左侧的别名更易读:

SELECT TOP 1 
    [name.family] = 'Surname',
    [name.given] = 'Forename, Middle Name',
    [name.prefix] = 'Title',

    [birthdate] = GETDATE(),
    [gender] = 'F',
    [active] = 'Yes',

    [telecom] = (
        SELECT
            [use] = 'work',
            [system] = V.system,
            [value] = '12344556'
        FROM
            (VALUES ('phone'), ('home')) AS V(system)
        FOR JSON 
            PATH)
FROM tblCustomer
FOR JSON 
    PATH

答案 1 :(得分:0)

SELECT  
       EMP.ID,
       EMP.NAME,
       DEP.NAME

FROM EMPLOYEE EMP INNER JOIN DEPARTMENT DEP ON EMP.DEPID=DEP.DEPID
WHERE EMP.SALARY>1000
FOR JSON PATH