Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making json keys lowercase Snowflake

I have a table that looks like

ID DATE FIRST_NAME H&P
12 2023-02-01 JESSICA 40
99 2023-02-03 MINA 98
12 2023-01-14 JACK 12

I've created another table containing these columns as columns by doing

SELECT ID, OBJECT_CONSTRUCT(*) as details
FROM MY_TABLE;
ID DETAILS
12 {"DATE":"2023-02-01", "FIRST_NAME":"JESSICA", "H&P":"40"}
99 {"DATE":"2023-02-03", "FIRST_NAME":"MINA", "H&P":"98"}
12 {"DATE":"2023-01-14", "FIRST_NAME":"JACK", "H&P":"12"}

Is there a way to modify the DETAILS column when using OBJECT_CONSTRUCT() so that the KEYS of the json are lowercase but the VALUES stay the same as they appear, so I could get something like

ID DETAILS
12 {"date":"2023-02-01", "first_name":"JESSICA", "h&p":"40"}
99 {"date":"2023-02-03", "first_name":"MINA", "h&p":"98"}
12 {"date":"2023-01-14", "first_name":"JACK", "h&p":"12"}

thanks! (I would like to do this without listing out the columns as my actual table has about 400 columns)

like image 882
Angie Avatar asked Oct 29 '25 19:10

Angie


2 Answers

Keys could be listed explicitly as lower cased:

CREATE OR REPLACE TABLE MY_TABLE(ID INT, DATE DATE, FIRST_NAME TEXT, "H&P" INT)
AS
SELECT 12,  '2023-02-01', 'JESSICA', 40 UNION
SELECT 99,  '2023-02-03', 'MINA', 98 UNION
SELECT 12,  '2023-01-14', 'JACK', 12;

SELECT ID, OBJECT_CONSTRUCT('date', DATE, 
                            'fist_name', FIRST_NAME,
                            'h&p', "H&P") AS details
FROM MY_TABLE;

Output:

ID DETAILS
12 { "date": "2023-02-01", "fist_name": "JESSICA", "h&p": 40 }
99 { "date": "2023-02-03", "fist_name": "MINA", "h&p": 98 }
12 { "date": "2023-01-14", "fist_name": "JACK", "h&p": 12 }

Using OBJECT constant syntax:

SELECT ID, {'date': DATE, 
            'fist_name': FIRST_NAME,
            'h&p': "H&P"} AS details
FROM MY_TABLE;

EDIT:

Is there a way to do it without explicitly listing the columns?

Yes, one option requires flattening and building object second time which will reduce the performance:

WITH cte AS (
  SELECT ID, OBJECT_CONSTRUCT(*) AS details
  FROM MY_TABLE
)
SELECT ID, OBJECT_AGG(LOWER(f.KEY), f.VALUE) AS details
FROM cte
,LATERAL FLATTEN(INPUT => cte.details) AS f
GROUP BY ID, SEQ;

Output:

enter image description here

like image 90
Lukasz Szozda Avatar answered Oct 31 '25 12:10

Lukasz Szozda


You can also do this with a very simple JavaScript UDF:

CREATE OR REPLACE FUNCTION lower_object_keys(
  OBJ OBJECT
)
  RETURNS OBJECT
  LANGUAGE JAVASCRIPT
  IMMUTABLE
AS
$$
  return Object.fromEntries(
    Object.entries(OBJ).map(
      ([k, v]) => [k.toLowerCase(), v]
    )
  );
$$;

And then you can easily do:

SELECT lower_object_keys(OBJECT_CONSTRUCT(*))
FROM ...
like image 35
Marco Roy Avatar answered Oct 31 '25 12:10

Marco Roy