POSTGRESQL copy jsonb value to new column - json

I want extract a json value from a column and insert it into a new one.
Example row as an insert statement copied:
INSERT INTO "table_name".("booking_number","arrival_date","departure_date","custom_fields","customer_id","import_id","id","at_table","a_la_carte","value")
VALUES
(E'00000007',E'2019-01-02 12:00:00',E'2020-02-05 12:00:00',E'[{"protelSurname": "Smith", "servicio_tags": ["protel-info"], "protelUniqueID": "[{\\"ID\\":\\"294623726\\",\\"Type\\":\\"21\\",\\"ID_Context\\":\\"GHA\\"},{\\"ID\\":\\"4842148\\",\\"Type\\":\\"1\\",\\"ID_Context\\":\\"protelIO\\"}]", "protelGivenName": "Seth"}, {"value": "3/3/3/3/3", "display_name": "Personen Anzahl", "servicio_tags": ["person-number-info"]}, {"value": "en", "display_name": "Sprache", "servicio_tags": ["language"]}, {"value": " Robotics", "display_name": "Begleiter", "servicio_tags": ["accompanied-guests"]}, {"value": "2. Januar 2019", "display_name": "Anreise", "servicio_tags": ["arrival"]}, {"value": "5. Februar 2020", "display_name": "Abreise", "servicio_tags": ["departure"]}, {"value": "EBROV RO", "display_name": "Rate Code", "servicio_tags": ["price-type"]}, {"value": "SSV", "display_name": "Zimmer Typ", "servicio_tags": ["room-type"]}, {"value": "2013", "display_name": "Zimmernummer", "servicio_tags": ["room-number"]}, {"value": "Australia", "display_name": "Nation", "servicio_tags": ["nation"]}, {"value": "", "display_name": "Gruppe", "servicio_tags": ["group-name"]}]',1,36020,369528,FALSE,FALSE,E'{"protelSurname": "Smith", "servicio_tags": ["protel-info"], "protelUniqueID": "[{\\"ID\\":\\"294623726\\",\\"Type\\":\\"21\\",\\"ID_Context\\":\\"GHA\\"},{\\"ID\\":\\"4842148\\",\\"Type\\":\\"1\\",\\"ID_Context\\":\\"protelIO\\"}]", "protelGivenName": "Seth"}');
I want to extract the protelUniqueID with the servicio-tag ["protel-info"]. In the best case only the ID value. In this case 294623726.
Then I want to create a new column named guest_profile_id in this table named guest_group and insert this value in for the same row.
So I think this needs to be done by the following steps:
Creating new column
Query id from json column
Insert id to new column
My try so far for step 2)
SELECT *
 FROM guest_group gg
cross join lateral jsonb_array_elements(custom_fields) 
WHERE value #> '{"servicio_tags": ["protel-info"]}'::jsonb
AND gg.customer_id = 1
Thanks for the help.

First of all protelUniqueID is a list. You need the only first ID from a list as I understood.
Note! "protelUniqueID": "[{\\"ID\\": .... looks like strange format. Is like json as string inside json. Anyway I share solution for your description.
CREATE TABLE my_tbl (custom_fields jsonb);
INSERT INTO my_tbl (custom_fields)
VALUES
(
E'{"protelSurname": "Smith", "servicio_tags": ["protel-info"], "protelUniqueID": "[{\\"ID\\":\\"294623726\\",\\"Type\\":\\"21\\",\\"ID_Context\\":\\"GHA\\"},{\\"ID\\":\\"4842148\\",\\"Type\\":\\"1\\",\\"ID_Context\\":\\"protelIO\\"}]", "protelGivenName": "Seth"}'
);
Let's try to select our ID(294623726):
SELECT
custom_fields::json->'servicio_tags' AS tags,
CAST(CAST(CAST(custom_fields::json->'protelUniqueID' AS jsonb)->>0 AS jsonb)->>0 AS jsonb)->>'ID' AS protel_first_id
FROM my_tbl;
-- tags,protel_first_id
--["protel-info"],294623726
All what we need is just add a column + update
ALTER TABLE my_tbl ADD COLUMN guest_profile_id INTEGER DEFAULT NULL;
UPDATE my_tbl set guest_profile_id = CAST(CAST(CAST(CAST(custom_fields::json->'protelUniqueID' AS jsonb)->>0 AS jsonb)->>0 AS jsonb)->>'ID' AS INTEGER) WHERE guest_profile_id IS NULL;
db-fiddle example
Note! You can remove 1 CAST if you'll use clear format:
INSERT INTO my_tbl (custom_fields)
VALUES
(
E'{"protelUniqueID": [{"ID":"294623726","Type":"21","ID_Context":"GHA"},{"ID":"4842148","Type":"1","ID_Context":"protelIO"}]}'
);
SELECT
CAST(CAST(custom_fields::json->'protelUniqueID' AS jsonb)->>0 AS jsonb)->>'ID' AS protel_first_id
FROM my_tbl;
Hope this helps.

Related

Extract sub JSON with keys and values in MYSQL

I have a table with a JSON TYPE column like this:
id
json_info
date
1.
{"Ccclaptop_model": {"value": "asus", "price": "2122"}, "laptop_ram": {"value": "6", "price": "122"}, "laptop_mouse_model": {"value": "logic", "price": "30"} , "laptop_keys_model": {"value": "USA", "price": "10"}}
2020-02-02
And I'd like to have a query that extracts a sub-JSON with his key value, like this:
id
json_info
date
1.
{"laptop_mouse_model": {"value": "logic", "price": "30"} , "laptop_keys_model": {"value": "USA", "price": "10"}}
2020-02-02
I have tried JSON_EXTRACT
SELECT id,
JSON_EXTRACT(json_info, '$.laptop_mouse_model', '$.laptop_keys_model' ) AS store_id
FROM feature_data WHERE date = '2020-02-02';
but just return a JSON array without keys, like this:
id
json_info
date
1.
[{"value": "logic", "price": "30"} ,{"value": "USA", "price": "10"}]
2020-02-02
Does somebody know if exists a function that I could use?
You can use JSON_OBJECT to combine result to a json, for example:
SELECT id,JSON_OBJECT('laptop_mouse_model',JSON_EXTRACT(json_info, '$.laptop_mouse_model'),'laptop_keys_model',JSON_EXTRACT(json_info, '$.laptop_keys_model')) AS store_id FROM feature_data WHERE date = '2020-02-02';

postgresql UPDATE to remove key/value from JSONB data type

Given the following table and data:
CREATE TABLE test (
slots jsonb
);
INSERT INTO test VALUES ('{"0": {"tag": "abc", "info": "xyz"}, "1": {"tag": "def", "info": "uvw"}}');
SELECT slots FROM test;
Now I want to delete the "1" key/value entirely. I can set it to null as follows:
UPDATE test SET slots['1'] = null;
SELECT slots FROM test;
But this returns:
{"0": {"tag": "abc", "info": "xyz"}, "1": null}
Whereas I want it to return:
{"0": {"tag": "abc", "info": "xyz"}}
What is the command/syntax to achieve this?
Use the - operator to remove a key completely
update test
set slots = slots - '1'

How to query nested array of jsonb

I am working on a PostgreSQL 11 table with a column of nested and multiple jsonb objects
to simulate the issue: -
CREATE TABLE public.test
(
id integer NOT NULL DEFAULT nextval('test_id_seq'::regclass),
testcol jsonb
)
insert into test (testcol) values
('[{"type": {"value": 1, "displayName": "flag1"}, "value": "10"},
{"type": {"value": 2, "displayName": "flag2"}, "value": "20"},
{"type": {"value": 3, "displayName": "flag3"}, "value": "30"},
{"type": {"value": 4, "displayName": "flag4"}},
{"type": {"value": 4, "displayName": "flag4"}},
{"type": {"value": 6, "displayName": "flag6"}, "value": "40"}]');
I am trying to:
get outer value if type= specific value. e.g. get the value 30, if flag3 is in displayname.
count occurrence of flag4 in inner json
You could use json_to_recordset to parse it:
WITH cte AS (
SELECT test.id, sub."type"->'value' AS t_value, sub."type"->'displayName' AS t_name, value
FROM test
,LATERAL jsonb_to_recordset(testcol) sub("type" jsonb, "value" int)
)
SELECT *
FROM cte
-- WHERE ...
-- GROUP BY ...;
db<>fiddle demo

Redshift - SQL script to extract value from a key value pair

I have a columns containing JSON data as below. I am trying to extract values corresponding to each key pair in the column. Could anyone advice how could I do using SQL
[{"id": 101, "id1": {"key": "SaleId", "type": "identifier", "regex": null}, "id2": {"key": Name, "type": "identifier", "regex": null}, "id3": {"key": null, "type": "identifier", "regex": null}}]
Key values are id1, id2, id3
Expected output:
id1 : SaleId
id2 : Name
id3 : null
I am using Redshift. Thanks
I don't know anything about Redshift, so this might not Work.
It Works in JavaScript:
/"(id\d)":\s\{"key": "?(\w+)"?/g
You will then have to extract Group 1, containing the id and Group 2, containing the key.
The regex starts by matching a double quote, then creating a Group with the Word 'id' followed by a digit, a colon, a Space, a left curly brace, a double quote, the Word 'key', a colon, a Space, an optional double quote. Finally it creates a Group with one or more Word characters, followed by an optional double quote.
As I said, I don't know Redshift, for instance, you might have to escape double quotes.
You can do what you need like this
with t as
(
select '[{"id": 101, ' ||
'"id1": {"key": "SaleId", "type": "identifier", "regex": "null"}, ' ||
'"id2": {"key": "Name", "type": "identifier", "regex": "null"}, ' ||
'"id3": {"key": "null", "type": "identifier", "regex": "null"}}]' as str
)
select 'id1:' || json_extract_path_text(substring(str,2,length(str)-2),'id1','key'),
'id2:' || json_extract_path_text(substring(str,2,length(str)-2),'id2','key'),
'id3:' || json_extract_path_text(substring(str,2,length(str)-2),'id3','key')
from t;
The JSON string in your example is invalid because Name is not in double quotes.
Assuming this is a typo and this is meant to be a valid JSON string, then you can use JSON functions to extract the values you need from the column.
Example (I have added quotes around "Name"):
create temp table jsontest (myjsonstring varchar(1000))
;
insert into jsontest(myjsonstring)
values ('[{"id": 101, "id1": {"key": "SaleId", "type": "identifier", "regex": null}, "id2": {"key": "Name", "type": "identifier", "regex": null}, "id3": {"key": null, "type": "identifier", "regex": null}}]')
;
select 'id1', json_extract_path_text(json_extract_array_element_text(myjsonstring, 0) , 'id1', 'key') from jsontest
union all
select 'id2', json_extract_path_text(json_extract_array_element_text(myjsonstring, 0) , 'id2', 'key') from jsontest
union all
select 'id3', json_extract_path_text(json_extract_array_element_text(myjsonstring, 0) , 'id3', 'key') from jsontest
;

How can I extract all values of a particular attribute within elements inside a JSON array in MySQL?

I've the below data stored in a column of MySQL table which is of "json" data type (MySQL v5.7.9)
[{"id": "26", "title": "similar1", "score": "0.97"}, {"id": "27", "title": "similar2", "score": "0.87"}, {"id": "28", "title": "similar2", "score": "0.87"}]
I need a MySQL query which will return me all the "title" values i.e. similar1, similar2 and similar3 and so on
Use JSON_EXTRACT().
mysql> create table t ( j json );
mysql> insert into t set j = '[{"id": "26", "title": "similar1", "score": "0.97"}, {"id": "27", "title": "similar2", "score": "0.87"}, {"id": "28", "title": "similar2", "score": "0.87"}]';
mysql> select json_extract(j, '$[*].title') from t;
+--------------------------------------+
| json_extract(j, '$[*].title') |
+--------------------------------------+
| ["similar1", "similar2", "similar2"] |
+--------------------------------------+
If you want to use JSON data in MySQL, you should read the docs on Functions that Search JSON Values, and learn to use the JSON search expressions.
This looks like a database design issue. It seems that you're using a json column when you should really be using another table to store these results as individual columns.
you can query like below
create table testTableforus (datapoint json);
insert into testTableforus
values
('{"id": "26", "title": "similar1", "score": "0.97"}'),
('{"id": "27", "title": "similar2", "score": "0.87"}'),
('{"id": "28", "title": "similar2", "score": "0.87"}');
select datapoint->"$.title" from testTableforus;
drop table testTableforus;
See working demo