How can I update an existing table with an array of objects? - sql

When the user clicks on another user, a new item is created in the chats table, with a sender and receiver id but an empty chat message.
when the user sends a message, depending on who he sends it to, the item in the chat table will be updated with the sent message.
the message object looks like this [{message: "abc", sender: "person",
reciever:"person2"}] // there will be multiple object inside the arr
at the moment this is how I my table look:
chats (sender_id, reciever_id, messages jsonb[])
and this is the query I'm sending
UPDATE chats SET
messages = '[
{ message: 'hi', sender: 'test', reciever: null },
{ message: 'hello', sender: 'test', reciever: null }
]' WHERE
sender_id = 47 AND
reciever_id = 43
This is causing errors, and not updating the table. The error doesn't tell me much, but I think it's due to the fact that my object is not in json format(strings on the keys)
so what data type can I use, to allow me to update my messages column using MY format.

You must use double quotes for json.
your data also doesn't need an jsonb array, so i removed it
CREATE TABLE chats (sender_id int, reciever_id int, messages jsonb)
CREATE TABLE
INSERT INTO chats VALUES (47,43, NULL)
INSERT 0 1
UPDATE chats SET
messages = '[
{ "message": "hi", "sender": "test", "reciever": null },
{ "message": "hello", "sender": "test", "reciever": null }
]' WHERE
sender_id = 47 AND
reciever_id = 43
UPDATE 1
SELECT * FROM chats
sender_id
reciever_id
messages
47
43
[{"sender": "test", "message": "hi", "reciever": null}, {"sender": "test", "message": "hello", "reciever": null}]
SELECT 1
fiddle

Related

Check if row contains a nested item in DynamoDB?

I am trying to use PartiQL with DynamoDB to perform SQL queries to check if a device is inactive and contains an error. Here's is the query I am using:
SELECT *
FROM "table"
WHERE "device"."active" = 0 AND "device"."error" IS NOT NULL
However I've noticed that even if a device doesn't have the error item, the query still returns a row. How can I query a device that only contains the error item?
With error item
{
"id": "value",
"name": "value,
"device": {
"active": 0,
"error": {
"reason": "value"
}
}
}
Without error item
{
"id": "value",
"name": "value,
"device": {
"active": 0
}
}
You're looking for IS NOT MISSING :) That's the partiql version of the filter expression operator function attribute_exists.
Given a table with a primary key PK, sort key SK, and the following data:
PK
SK
myMap
foo
1
{}
foo
2
{"test": {}}
-- Returns both foo 1 and foo 2
SELECT *
FROM "my-table"
WHERE "PK" = 'foo' AND "myMap"."test" IS NOT NULL
-- Returns just foo 2
SELECT *
FROM "my-table"
WHERE "PK" = 'foo' AND "myMap"."test" IS NOT MISSING
Also made sure my example specifies the PK in the WHERE clause - otherwise, your query will be a full scan. Maybe that's what you want, though. Just something to be aware of.

How can i get keys from each object in array (postgresql)?

I done
let statuses = await t.any(`SELECT DISTINCT status FROM mails`)
and got
"statuses": [
{
"status": "error"
},
{
"status": "success"
}
]
How can I get array with keys of objects ? ['error', 'success'] ?
Assuming status is a jsonb column (which it should be), you can do:
select distinct st.status
from mails m
cross join jsonb_array_elements(m.status -> 'statuses') as st(status)
If status is a json column you will need to use json_array_elements() instead

MSSQL Query JSON displays Null value

I have a table PublicRelations with a column called Students in a SQL Server database called Subjects.
[
{ "Label": "Name", "ColumnValue": "Trudie" },
{ "Label": "Class", "ColumnValue": "PublicRelations" },
{ "Label": "Room", "ColumnValue": "8049" },
{ "Label": "HttpPath", "ColumnValue": "https://www.google.com/" }
]
I only get NULL when I run the below query using the Json_value. I'd like to get it to display the value from the array. I believe this may have to do with the 4000 character limit?
SELECT [StuduentID],
[Students],
--JSON_VALUE([Students],'$.ColumnValue') AS Name --Only returns NULL
FROM [Subjects].[dbo].[PublicRelations] c
CROSS APPLY OPENJSON(c.Students)
WITH ( Name int '$.Name',
Value nvarchar(255) '$.ColmunValue'
) AS jsonValues
WHERE jsonValues.ColumnValue = 'Trudie'
The query works and I can find what I need, but again, I only get NULL when I want to display that part of the JSON column in my results.
The statement is wrong and you has the following issues (as #MartinSmith already mentioned):
Syntax error - '$.ColmunValue' should be '$.ColumnValue'.
Wrong schema definition (the WITH clause) - I can't see Name key in the input JSON.
Wrong use of JSON_VALUE() - this function extracts scalar value from a JSON string, so JSON_VALUE([Students],'$.ColumnValue') returns NULL with this JSON input in lax mode.
You may try with the following statement (based on the statement in the question):
Table:
CREATE TABLE PublicRelations (
StudentID int,
Students nvarchar(1000))
INSERT INTO PublicRelations (StudentID, Students)
VALUES (1, N'[
{ "Label": "Name", "ColumnValue": "Trudie" },
{ "Label": "Class", "ColumnValue": "PublicRelations" },
{ "Label": "Room", "ColumnValue": "8049" },
{ "Label": "HttpPath", "ColumnValue": "https://www.google.com/" }
]')
Statement:
SELECT p.StudentID, j.*
FROM [PublicRelations] p
CROSS APPLY OPENJSON(p.Students) WITH (
Name nvarchar(50) '$.Label',
Value nvarchar(255) '$.ColumnValue'
) j
WHERE EXISTS (
SELECT 1
FROM OPENJSON(p.Students) WITH (Value nvarchar(255) '$.ColumnValue')
WHERE Value = N'Trudie'
) AND (j.Name IN ('Name', 'Class', 'Room'))
Result:
StudentID Name Value
1 Name Trudie
1 Class PublicRelations
1 Room 8049

Can I convert a stringified JSON array back to a BigQuery strucutre?

I'm trying to take a STRING field that contains a nested JSON structure from a table called my_old_table, extract a nested array called "alerts" from it, then insert it into a column in a new table called my_new_table. The new column is defined as:
ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>>
I'm using this SQL:
INSERT INTO my_dataset.my_table(
id, alerts)
SELECT id, JSON_EXTRACT(extra, "$.alerts") AS content_alerts
FROM my_dataset.my_old_table
This gives me:
Query column 2 has type STRING which cannot be inserted into column content_alerts, which has type ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>> at [4:1]
I don't see a way of parsing the extracted string this back to a structure.... Is there another way to do this?
Edit:
The original value is a json string that looks like this:
{
"id": "bar123",
"value": "Test",
"title": "Test",
"alerts": [
{
"id": "abc123",
"title": "Foo",
"created": "2020-01-17T23:18:59.769908Z"
},
{
"id": "abc124",
"title": "Accepting/Denying Claims",
"created": "2020-01-17T23:18:59.769908Z"
}
]
}
I want to extract $.alerts and insert it into the ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>> somehow.
Edit #2
To clarify, this reproduces the issue:
CREATE TABLE insights.my_table
(
id string,
alerts ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>>
);
CREATE TABLE insights.my_old_table
(
id string,
field STRING
);
INSERT INTO insights.my_old_table(id, field)
VALUES("1", "{\"id\": \"bar123\",\"value\": \"Test\",\"title\": \"Test\",\"alerts\":[{\"id\": \"abc123\",\"title\": \"Foo\",\"created\": \"2020-01-17T23:18:59.769908Z\"},{\"id\": \"abc124\",\"title\": \"Accepting/Denying Claims\",\"created\": \"2020-01-17T23:18:59.769908Z\"}]}");
Based on the above setup, I don't know how to extract "alerts" from the STRING field and insert it into the STRUCT field. I thought I could add a JSON PARSE step in there but I don't see any BigQuery feature for that. Or else there would be a way to manipulate JSON as a STRUCT but I don't see that either. As a result, this is as close as I could get:
INSERT INTO insights.my_table(id, alerts)
SELECT id, JSON_EXTRACT(field, "$.alerts") AS alerts FROM insights.my_old_table
I'm sure there's something I'm missing here.
Below for BigQuery Standard SQL
#standardSQL
CREATE TEMP FUNCTION JsonToItems(input STRING)
RETURNS ARRAY<STRING>
LANGUAGE js AS """
return JSON.parse(input).map(x=>JSON.stringify(x));
""";
)
SELECT
JSON_EXTRACT_SCALAR(extra, "$.id") AS id,
ARRAY(
SELECT AS STRUCT
JSON_EXTRACT_SCALAR(alert, "$.id") AS cuid,
JSON_EXTRACT_SCALAR(alert, "$.title") AS title,
TIMESTAMP(JSON_EXTRACT_SCALAR(alert, "$.created")) AS created
FROM UNNEST(JsonToItems(JSON_EXTRACT(extra, "$.alerts"))) alert
) AS alerts,
FROM `project.dataset.my_old_table`
You can test, play with above using sample data from your question as in example below
#standardSQL
CREATE TEMP FUNCTION JsonToItems(input STRING)
RETURNS ARRAY<STRING>
LANGUAGE js AS """
return JSON.parse(input).map(x=>JSON.stringify(x));
""";
WITH `project.dataset.my_old_table` AS (
SELECT '''
{
"id": "bar123",
"value": "Test",
"title": "Test",
"alerts": [
{
"id": "abc123",
"title": "Foo",
"created": "2020-01-17T23:18:59.769908Z"
},
{
"id": "abc124",
"title": "Accepting/Denying Claims",
"created": "2020-01-17T23:18:59.769908Z"
}
]
}
''' extra
)
SELECT
JSON_EXTRACT_SCALAR(extra, "$.id") AS id,
ARRAY(
SELECT AS STRUCT
JSON_EXTRACT_SCALAR(alert, "$.id") AS cuid,
JSON_EXTRACT_SCALAR(alert, "$.title") AS title,
TIMESTAMP(JSON_EXTRACT_SCALAR(alert, "$.created")) AS created
FROM UNNEST(JsonToItems(JSON_EXTRACT(extra, "$.alerts"))) alert
) AS alerts,
FROM `project.dataset.my_old_table`
with result
Obviously, you can then use this in your INSERT INTO my_dataset.my_table statement
You can parse the extracted string back to a BigQuery structure like so:
SELECT STRUCT(ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>>
[('Rick', 'Scientist', '2020-01-17')]) FROM my_dataset.my_old_table;
I just tried it with your data
I have inserted your data in a BigQuery table:
INSERT INTO dataset.table
VALUES('{"id": "bar123", "value": "Test", "title": "Test", "alerts":
[{ "id": "abc123", "title": "Foo", "created": "2020-01-17T23:18:59.769908Z"},
{"id": "abc124", "title": "Accepting/Denying Claims", "created": "2020-01-17T23:18:59.769908Z"}]}');
and queried it, converting it back to a BigQuery structure:
SELECT STRUCT<cuid STRING, title STRING, created TIMESTAMP>("abc123",
"Foo", "2020-01-17T23:18:59.769908Z"),("abc124", "Accepting/Denying
Claims", "2020-01-17T23:18:59.769908Z") FROM blabla.testingjson;
Output:
Row | f0_.cuid | f0_.title | f0_.created
----------------------------------------
1 | abc123 | Foo | 2020-01-17 23:18:59.769908 UTC

Postgresql SELECTing from JSON column

Assume I am using PG 9.3 and I have a post table with a json column 'meta_data':
Example content of the json column 'meta_data'
{
"content": "this is a post body",
"comments": [
{
"user_id": 1,
"content": "hello"
},
{
"user_id": 2,
"content": "foo"
},
{
"user_id": 3,
"content": "bar"
}
]
}
How can I find all the posts where the user_id = 1 from the comments array from the meta_data column?
I'm almost positive I'm implementing this incorrectly but try this
select *
from posts
where id in (
select id from (
select id,
json_array_elements(meta_data->'comments')->'user_id' as user_id
from posts
) x
where cast(user_id as varchar) = '1'
);
There's probably an array operator like #> that will remove the need for the nested select statements but I can't seem to get it to work right now.
Let me know if this is going down the correct track, I'm sure we could figure it out if required.