Search code examples
sqljsonsql-servert-sqlsql-server-2016

Filter JSON data by a sibling property's value


Sample Data Setup:

DECLARE @Data TABLE (Id INT IDENTITY(1,1), JSONData NVARCHAR(MAX))
INSERT INTO @Data
VALUES ( N'
{
    "propId": 0,
    "propName": "Helo.World",
    "dataDump": [   {
                        "propId": 0,
                        "propName": "fName",
                        "val": "John"
                    },
                    {
                        "propId": 0,
                        "propName": "lName",
                        "val": "Doe",
                        "dataDump": [   {
                                            "propId": 0,
                                            "propName": "homePhone",
                                            "val": "1010101010"
                                        },
                                        {
                                            "propId": 0,
                                            "propName": "mobilePhone",
                                            "val": "010101010101"
                                        }
                                    ]
                    },
                    {
                        "propId": 0,
                        "propName": "isAuthorized",
                        "val": "true"
                    },
                    {
                        "propId": 0,
                        "propName": "isFullAccess",
                        "val": "false"
                    }
                ]
}' ),
( N'
{
    "propId": 0,
    "propName": "Helo.World",
    "dataDump": [   {
                        "propId": 0,
                        "propName": "fName",
                        "val": "Joe"
                    },
                    {
                        "propId": 0,
                        "propName": "lName",
                        "val": "Harris",
                        "dataDump": [   {
                                            "propId": 0,
                                            "propName": "homePhone",
                                            "val": "2020202020"
                                        }
                                    ]
                    },
                    {
                        "propId": 0,
                        "propName": "isAuthorized",
                        "val": "true"
                    },
                    {
                        "propId": 0,
                        "propName": "isFullAccess",
                        "val": "true"
                    }
                ]
}' ), (N'
{
    "propId": 0,
    "propName": "Helo.World",
    "dataDump": [   {
                        "propId": 0,
                        "propName": "fName",
                        "val": "Olivia"
                    },
                    {
                        "propId": 0,
                        "propName": "lName",
                        "val": "Smith"
                    },
                    {
                        "propId": 0,
                        "propName": "isAuthorized",
                        "val": "false"
                    },
                    {
                        "propId": 0,
                        "propName": "isFullAccess",
                        "val": "false"
                    }
                ]
}' ),( N'
{
    "propId": 0,
    "propName": "Helo.World",
    "dataDump": [   {
                        "propId": 0,
                        "propName": "fName",
                        "val": "George"
                    },
                    {
                        "propId": 0,
                        "propName": "lName",
                        "val": "Hart",
                        "dataDump": [   {
                                            "propId": 0,
                                            "propName": "homePhone",
                                            "val": "3030303030"
                                        },
                                        {
                                            "propId": 0,
                                            "propName": "mobilePhone",
                                            "val": "030303030303"
                                        }
                                    ]
                    },
                    {
                        "propId": 0,
                        "propName": "isFullAccess",
                        "val": "false"
                    }
                ]
}' ) ;

SELECT [Id]
     , [JSONData]
FROM @Data
-- WHERE [JSONData].dataDump.propName = 'isAuthorized'
--       AND [JSONData].dataDump.val = 'true'

Goal:

To return Id and JSON of the records that has "[JSONData].dataDump.propName" = 'isAuthorized' and "[JSONData].dataDump.val" = 'true'

Expected output:

1st and 2nd records should be returned since, eventhough 3rd record has "[JSONData].dataDump.propName" = 'isAuthorized', it however does not have its "[JSONData].dataDump.val" = 'true' (it's 'false') and 4th record doesn't even have this property.

I'm completely new to parsing JSON within SQL Server and not finding similar examples that filters by sibling values.

My (unsuccessful) try:

SELECT  *
FROM    @Data AS [T]
CROSS APPLY
        OPENJSON ( [T].[JSONData], '$.dataDump' )
            WITH
                ( [propName] NVARCHAR ( 100 )
                , [val] NVARCHAR ( MAX ) AS JSON ) AS [dat]
WHERE   [dat].[propName] = 'isAuthorized'
        AND [dat].[val] = 'true' ;

This doesn't seem to return ANY data.


Solution

  • Pretty close, but val is just a string like propName. So

    SELECT *
    FROM @Data
    cross apply openjson(JSONData,'$.dataDump') 
    with 
    (
      propName nvarchar(200),
      val      nvarchar(200)
    )
    where propName = 'isAuthorized'
      and val = 'true'