Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to select multiple rows to a json array with a single top level field (column) that is not repeated

I have a table of items and content items. Each item has one content item.

I would like to select the rows to a JSON array but on the same level as the array I need an identifier field which must not repeat.

Here is an example of what I expect the output to be. At the top level, there is a single identifier field and then an array of items.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

{
        "Identifier": "71A08718-4D35-4661-BCB9-DA8BA13F005E",

        "Items": [{
        "RecipientName": "Name1",
        "RecipientSurname": "Surname1",
        "RecipientContactNumber": "10001000",
        "RecipientEmail": "email@email.com",
        "Contents": {
            "ItemDescription": "description 1",
            "ItemQuanity": 1,
            "ItemNetWeightg": 10
        }
    }, {
        "RecipientName": "Name2",
        "RecipientSurname": "Surname2",
        "RecipientContactNumber": "20002000",
        "RecipientEmail": "email2email2.com",
        "Contents": {
            "ItemDescription": "description 1",
            "ItemQuanity": 1,
            "ItemNetWeightg": 10
        }
    }
]
}

But the identifier is repeated in each item. This is what I am getting currently. The identifier is repeated inside each item in the array.

{
    "Items": [{
            "Identifier": "71A08718-4D35-4661-BCB9-DA8BA13F005E",
            "RecipientName": "Name1",
            "RecipientSurname": "Surname1",
            "RecipientContactNumber": "10001000",
            "RecipientEmail": "email@email.com",
            "Contents": {
                "ItemDescription": "description 1",
                "ItemQuanity": 1,
                "ItemNetWeightg": 10
            }
        }, {
            "Identifier": "329CC547-D418-4863-A50C-DFB072B66FE7",
            "RecipientName": "Name2",
            "RecipientSurname": "Surname2",
            "RecipientContactNumber": "20002000",
            "RecipientEmail": "email2email2.com",
            "Contents": {
                "ItemDescription": "description 1",
                "ItemQuanity": 1,
                "ItemNetWeightg": 10
            }
        }
    ]
}

Here is what I have tried.

First some sample data. There are 2 tables. First the items table. This is followed by the content items table. For the example I insert 2 rows into each table. The content items are linked to the items using the OrderNumber column.

DECLARE @Items TABLE (
ID bigint
,Number nvarchar(20)
,Date datetime2
,OASNumber nvarchar(20)
,ContactName nvarchar(50)
,ContactSurname nvarchar(50)
,Mobile nvarchar(20)
,Email nvarchar(50)
,Type nvarchar(50)
)

DECLARE @ContentItems TABLE 
(Id bigint
,OrderNumber nvarchar(50)
,ItemDescription nvarchar(max)
,Quantity int
)

INSERT INTO @Items
SELECT
1,'ON1',GETDATE(),'OAS1','Name1','Surname1','10001000','email@email.com','Sales of Goods'
INSERT INTO @ContentItems
SELECT
1,'ON1','description 1',1

INSERT INTO @Items
SELECT
2,'ON2',GETDATE(),'OAS2','Name2','Surname2','20002000','email2email2.com','Sales of Goods'
INSERT INTO @ContentItems
SELECT
3,'ON2','description 1',1

SELECT * FROM
(
SELECT 
    NEWID() AS Identifier
    ,D.ContactName AS [RecipientName]
    ,D.ContactSurname AS [RecipientSurname]
    ,D.Mobile AS [RecipientContactNumber]
    ,D.Email AS [RecipientEmail]
    ,Item.ItemDescription AS [Contents.ItemDescription]
    ,Item.Quantity AS [Contents.ItemQuanity]
    ,10 AS [Contents.ItemNetWeightg]
FROM @Items D
JOIN @ContentItems Item ON Item.OrderNumber = D.Number
) X
FOR JSON PATH, ROOT('Items')

>Solution :

You need to nest your FOR JSON clauses

SELECT
  NEWID() AS Identifier,
  (
    SELECT 
       i.ContactName AS RecipientName
      ,i.ContactSurname AS RecipientSurname
      ,i.Mobile AS RecipientContactNumber
      ,i.Email AS RecipientEmail
      ,ci.ItemDescription AS [Contents.ItemDescription]
      ,ci.Quantity AS [Contents.ItemQuanity]
      ,10 AS [Contents.ItemNetWeightg]
    FROM Items i
    JOIN ContentItems ci ON ci.OrderNumber = i.Number
    FOR JSON PATH
  ) AS Items
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;

db<>fiddle

You can also nest it further, for example if you want Items and ContentItems as nested arrays.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading