Home > other >  Complications trying to exclude a specific column from a Json object why writing an SQL query on sno
Complications trying to exclude a specific column from a Json object why writing an SQL query on sno

Time:03-15

I am new to Snowflake and I am trying to write an SQL query to create a JSON object while excluding a specific column from the output

table: lex

id Amount status
001 200 accept
001 100 accept
002 200 accept
002 100 accept
003 200 accept

my codes so far

With wt as (
    Select *
    FROM lex
),
-------Convert to JSON------
wt_json as (
    select id,
            ARRAY_AGG(object_construct_keep_null(*)) withdrawals
    from wt
    Group by id
)
select *  from wt_json

this produces an output similar to this

id withdrawals
01 [{id: 01, amount :200, status: accept},{id: 01, amount :100,status: accept}]
02 [{id: 02, amount :200, status: accept},{id: 02, amount :100,status: accept}]
03 [{id: 03, amount :200, status: accept}]

However, I am trying to exclude the Id in the JSON object.

what I am trying to achieve

id withdrawals
01 [{ amount :200, status: accept},{ amount :100,status: accept}]
02 [{ amount :200, status: accept},{ amount :100,status: accept}]
03 [{ amount :200, status: accept}]

CodePudding user response:

You are using * in the object_construct_keep_null function. This means the object is constructed from from all available columns. If you don't want this then instead specify each column that you do want, in the form 'key', value. You can include the "id" column separately to achieve what you want:

WITH src AS (
    SELECT '01' AS "id", 200 AS "amount", 'accept' AS "status"
    UNION ALL 
    SELECT '01' AS "id", 100 AS "amount", 'accept' AS "status"
    UNION ALL 
    SELECT '02' AS "id", 200 AS "amount", 'accept' AS "status"
    UNION ALL 
    SELECT '02' AS "id", 100 AS "amount", 'accept' AS "status"
    UNION ALL 
    SELECT '03' AS "id", 200 AS "amount", 'accept' AS "status"
)
SELECT 
      "id"
    ,  array_agg(
          object_construct_keep_null(
                'amount', "amount", 
                'status', "status"
          )
       ) AS "withdrawals"
FROM src
GROUP BY "id"

Result:

id     withdrawals
---------------------------------------------------------------------------------------------------
01  [  {    "amount": 200,    "status": "accept"  },  {    "amount": 100,    "status": "accept"  }]
02  [  {    "amount": 200,    "status": "accept"  },  {    "amount": 100,    "status": "accept"  }]
03  [  {    "amount": 200,    "status": "accept"  }]

CodePudding user response:

So the problem with OBJECT_DELETE is the id has to be the same case as the key, as JSON is case sensitive, and yet SQL is not, and thus by default it all becomes upper case, thus in my code below given I allow id to be non-qouted, it really is 'ID' for the OBJECT_DELETE command.

thus:

WITH wt AS (
    SELECT * FROM VALUES
        ('001', 200, 'accept'),
        ('001', 100, 'accept'),
        ('002', 200, 'accept'),
        ('002', 100, 'accept'),
        ('003', 200, 'accept')
        v(id, amount, status)
)
SELECT w.id,
    ARRAY_AGG(object_construct_keep_null(*)) AS org_withdrawals,
    ARRAY_AGG(object_delete(object_construct_keep_null(*),'ID')) AS del_withdrawals,
    ARRAY_AGG(object_construct_keep_null('amount', w.amount, 'status', w.status)) AS add_withdrawals
FROM wt as w
GROUP BY 1;
ID ORG_WITHDRAWALS DEL_WITHDRAWALS ADD_WITHDRAWALS
001 [ { "AMOUNT": 200, "ID": "001", "STATUS": "accept" }, { "AMOUNT": 100, "ID": "001", "STATUS": "accept" } ] [ { "AMOUNT": 200, "STATUS": "accept" }, { "AMOUNT": 100, "STATUS": "accept" } ] [ { "amount": 200, "status": "accept" }, { "amount": 100, "status": "accept" } ]
003 [ { "AMOUNT": 200, "ID": "003", "STATUS": "accept" } ] [ { "AMOUNT": 200, "STATUS": "accept" } ] [ { "amount": 200, "status": "accept" } ]
002 [ { "AMOUNT": 200, "ID": "002", "STATUS": "accept" }, { "AMOUNT": 100, "ID": "002", "STATUS": "accept" } ] [ { "AMOUNT": 200, "STATUS": "accept" }, { "AMOUNT": 100, "STATUS": "accept" } ] [ { "amount": 200, "status": "accept" }, { "amount": 100, "status": "accept" } ]

If you want control of the case of your output object, I would go the OBJECT_CONSTRUST direction, as there you have independent control. But if you are concerned the table will change shape, OR there are many columns, the * - ID approach, might be the simplest, albeit less performant option.

CodePudding user response:

Using OBJECT_DELETE:

Returns an object containing the contents of the input (i.e.source) object with one or more keys removed.

With wt as (
    Select *
    FROM  lex
 ),
-------Convert to JSON------
wt_json as (
   select id,
       ARRAY_AGG(OBJECT_DELETE(object_construct_keep_null(*), 'id')) withdrawals
   from wt
   Group by id
)
select *  from wt_json
  • Related