SQL в JSON - группировка результатов в массив JSON - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь найти решение 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

И это будетоднако вложите элементы в соответствии с моими отступами именования:

Свойство telecom.use не может быть сгенерировано в выводе JSON из-за конфликта с другим именем столбца или псевдонимом.Используйте разные имена и псевдонимы для каждого столбца в списке SELECT.

Есть ли способ обработать эту вложенность с помощью SQL или мне нужно будет создать отдельные запросы JSON и объединить их?

Спасибо

Использование @@ версии Microsoft SQL Server 2017 (окончательная первоначальная версия) - 14.0.1000.169 (X64) 22 августа 2017 г. 17:04:49 Copyright (C) 2017 Microsoft Corporation Express Edition (64-разрядная версия)) в Windows Server 2012 R2 Datacenter 6.3 (сборка 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

Элементы "value" будут взяты из столбцов в таблице 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 голосов
/ 20 августа 2019
SELECT TOP 1  
 --Candidate Details  
 --Key Field for Candidate 'ID'  
 --ISNULL(LMP.PROSPECTID,0)         AS 'ID',  

 --ISNULL(LMP.PROSPECTNUMBER,'')        AS 'CandidateCode',   
 ISNULL(LMP.FIRSTNAME,'')           AS 'FirstName',      
 ISNULL(LMP.MIDDLENAME,'')          AS 'MiddleName',      
 ISNULL(LMP.LASTNAME,'')            AS 'LastName',      
 ISNULL(LMP.FULLNAME,(ISNULL(LMP.FIRSTNAME,'') + ' ' + ISNULL(LMP.LASTNAME,'')) ) AS 'FullName',   

 --ISNULL(LMP.DISTRIBUTIONCODE,'')  AS 'DistributionCode',      
 ISNULL(RECOPT.GOCODE,'')           AS 'GOCode',      
 ISNULL(dbo.ClrDecrypt(LMP.ENCRYPTEDSSN,(select top 1 VALUE from SYSTEM where PROPERTY = 'EncryptionKey')),'')    AS 'SSN',  
 ISNULL(UDF.FIELD14,'')             AS 'PreferredEmail',  
 ISNULL(UDF.FIELD23,'')             AS 'RecruiterName',  
 ISNULL(UDF.FIELD24,'')             AS 'RecruiterEmail', 

 --Address Details 
 'AddresssList'=ISNULL((SELECT 
                --Key Field for Address 'ADDRESSID'
                --ISNULL(ADDR.ADDRESSID,0)      AS 'ADDRESSID',
                ISNULL(ADDRT.NAME,'')           AS 'AddressType',  
                ISNULL(ADDR.ADDRESSLINE1,'')    AS 'AddressLine1', 
                ISNULL(ADDR.ADDRESSLINE2,'')    AS 'AddressLine2', 
                ISNULL(ADDR.STATE,'')           AS 'State',  
                ISNULL(ADDR.CITY,'')            AS 'City',  
                ISNULL(ADDR.ZIPCODE,'')         AS 'ZipCode',  
                ISNULL(ADDR.COUNTY,'')          AS 'County',  
                ISNULL(ADDR.COUNTRY,'')         AS 'Country'   

    FROM  ADDRESS ADDR   
    LEFT JOIN ADDRESSTYPE ADDRT ON ADDRT.ADDRESSTYPEID=ADDR.ADDRESSTYPEID 
    WHERE ADDR.ENTITYID=LMP.PROSPECTID 
    FOR JSON PATH,INCLUDE_NULL_VALUES    
  ),'[]'),                   

 --EmploymentDetails  
   'EmploymentHistoryList'=ISNULL((SELECT
                            --Key Field for EmploymentHistory 'EmploymentHistoryID'  
                            --ISNULL(EMPH.EmploymentHistoryID,0)    AS 'EmploymentHistoryID',  

                            ISNULL(EMPH.EMPLOYERNAME,'')        AS 'EmployerName',  
                            ISNULL(EMPH.JOBTITLE,'')            AS 'JobTitle',  
                            ISNULL(EMPH.CITY,'')                AS 'EHCity',  
                            ISNULL(EMPH.STATE,'')               AS 'EHState',  
                            ISNULL(EMPH.COUNTY,'')              AS 'EHCounty',  
                            ISNULL((CASE WHEN EMPH.COUNTRY = -1 THEN '' ELSE EMPH.COUNTRY END) ,'') AS 'EHCountry',   
                            ISNULL(EMPH.ZIPCODE,'')             AS 'EHZipCode',  
                            ISNULL(EMPH.MANAGERFIRSTNAME,'')    AS 'ManagerFirstName',  
                            ISNULL(EMPH.MANAGERLASTNAME,'')     AS 'ManagerLastName',  

                            CONCAT(ISNULL(EMPH.MANAGERFIRSTNAME,''),' ', ISNULL(EMPH.MANAGERLASTNAME,''))   AS 'ManagerFullName',
                            ISNULL(EMPH.MANAGERJOBTITLE,'')     AS 'ManagerJobTitle',  
                            ISNULL(EMPH.MANAGERPHONENO,'')      AS 'ManagerPhoneNo'  
                            --ISNULL(CONVERT(varchar(20), EMPH.EMPLOYEDFROMDATE),'')    AS 'EmployedFromDate',  
                            --ISNULL(CONVERT(varchar(20), EMPH.EMPLOYEDTODATE),'')  AS 'EmployedToDate' 
    FROM 
   EmploymentHistory EMPH WHERE EMPH.ENTITYID=LMP.PROSPECTID
   FOR JSON PATH,INCLUDE_NULL_VALUES    
   ),'[]')  

FROM LM_PROSPECT LMP   
LEFT JOIN CRM_RECRUITMENTOPPORTUNITY RECOPT ON LMP.PROSPECTID=RECOPT.PROSPECTID      
LEFT JOIN UDFIELD UDF ON UDF.ENTITYID=LMP.PROSPECTID AND UDF.SUBCATEGORYLAYOUTID IN   
(SELECT TOP 1 SUBCATEGORYLAYOUTID FROM  TRK_SUBCATEGORY SUBC INNER JOIN TRK_LAYOUT LAYT ON LAYT.SUBCATEGORYID=SUBC.SUBCATEGORYID   
AND SUBC.SUBCATEGORYNAME='NYL_CandidateIntegration_Additioanl')  
WHERE LMP.PROSPECTNUMBER='VUE00000733'  
FOR JSON PATH,INCLUDE_NULL_VALUES,    
without_array_wrapper  
0 голосов
/ 13 февраля 2019

Использование подвыбора с несколькими жестко заданными строками:

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
...