Query json column based on the integer value in Postgres - json

I am using postgres v9.3
I have a table called temp which have a column all_data. The value looks something like below :-
{"Accountid" : "1364", "Personalid" : "4629-87c3-04e6a7a60208", "quote_number" : "QWQA62364384"}
Now, I want to query the all_data column by accountid=1364.
Could you please tell what would be the query?

Use the ->> operator
select *
from temp
where all_data ->> 'Accountid' = '1364';
Online example for 9.3: http://sqlfiddle.com/#!15/55981/1
However the above will not work if the JSON contains an array instead of a JSON object. E.g. a value like '[1,2]'::json will cause that query to fail.
With 9.4 and above you could check that using json_typeof() but with your soon to be unsupported version the only workaround I can think of is to convert the column to text and exclude those that start with a [
with valid_rows as (
select *
from temp
where all_data::text not like '[%'
)
select *
from valid_rows
where all_data ->> 'Accountid' = '1364';
Online example for 9.3: http://sqlfiddle.com/#!15/d01f43/3

Related

Athena CTAS saves json as string with special char escaped

I'm creating a new table using CTAS in athena, everything works fine except json string in the raw table (not defined as a struct).
It was
"screen_orientation":"{"angle":"0"}",
Now becomes:
"screen_orientation":"{\"angle\":\"0\"}",
CTAS statement is straight forward:
CREATE TABLE destination_table
WITH (
format='JSON',
partitioned_by=ARRAY['partition_date'],
write_compression='GZIP'
)
AS
SELECT * FROM src_table
Source column is of type string.
Is there anyway I could prevent this from happening? I can't redefine the source table's column definition due to permission issue.
The behavior is expected in Athena. For example if I run below query where I am casting a string to JSON then the double quotes are escaped by backslash(\).
SQL:
WITH dataset AS (
SELECT
CAST('{"test": "value"}' AS JSON) AS hello_msg
)
SELECT * FROM dataset
Output:
But you can always work around this by using json_format function as shown below :
SQL:
WITH dataset AS (
SELECT
json_format(JSON '{"test": "value"}' ) as hello_msg
)
SELECT * FROM dataset
Output:
So you can add json_format to your select query in CTAS statement which will not embed these backslashes.
If your json comes as a string you can also use json_parse:
WITH dataset AS (
SELECT
json_parse('{"test": "value"}') as hello_msg
)
SELECT * FROM dataset

Check if boolean value present in nested object

I have a JSON column and the data stored looks like:
{"results":{"made":true,"cooked":true,"eaten":true}}
{"results":{"made":true,"cooked":true,"eaten":false}}
{"results":{"made":true,"eaten":true,"a":false,"b":true,"c":false}, "more": {"ignore":true}}
I need to find all rows where 1+ values in $.results is false.
I tried using JSON_CONTAINS() but didn't find a way to get it to compare to a boolean JSON value, or to look at all values in $.results.
This needs to work with MySQL 5.7 but if it's not possible I will accept a MySQL 8+ answer.
I don't know the way for to search for a JSON true/false/null value using JSON functions - in practice these values are treated as string-type values during the search with JSON_CONTAINS, JSON_SEARCH, etc.
Use regular expression for the checking. Something like
SELECT id,
JSON_PRETTY(jsondata)
FROM test
WHERE jsondata REGEXP '"results": {[^}]+: false.*}';
DEMO
You could simply search the JSON_EXTRACT using the LIKE condition this way.
SELECT * FROM table1 WHERE JSON_EXTRACT(json_dict, '$.results') LIKE '%: false%';
Check this DB FIDDLE
An alternative to the pattern matching in other answers, is to extract all values from $.results and check each entry with a helper table with running numbers
SELECT DISTINCT v.id, v.json_value
FROM (
SELECT id, json_value, JSON_EXTRACT(json_value, '$.results.*') value_array
FROM json_table
) v
JOIN seq ON seq.n < JSON_LENGTH(v.value_array)
WHERE JSON_EXTRACT(v.value_array, CONCAT('$[', seq.n, ']')) = false
Here is the demo

How to extract a value from JSON that repeats multiple times?

I have the following table:
I need to create a select that returns me something like this:
I have tried this code:
SELECT Code, json_extract_path(Registers::json,'sales', 'name')
FROM tbl_registers
The previous code returns me a NULL in json_extract_path, I have tried the operator ::json->'sales'->>'name', but doesn't work too.
You need to unnest the array, and the aggregate the names back. This can be done using json_array_elements with a scalar sub-query:
select code,
(select string_agg(e ->> 'name', ',')
from json_array_elements(t.products) as x(e)) as products
from tbl_registers t;
I would also strongly recommend to change your column's type to jsonb
step-by-step demo:db<>fiddle
SELECT
code,
string_agg( -- 3
elems ->> 'name', -- 2
','
) as products
FROM tbl_registers,
json_array_elements(products::json) as elems -- 1
GROUP BY code
If you have type text (strictly not recommended, please use appropriate data type json or jsonb), then you need to cast it into type json (I guess you have type text because you do the cast already in your example code). Afterwards you need to extract the array elements into one row per element
Fetch the name value
Reaggregate by grouping and use string_agg() to create the string list

how to ORDER BY json object in MySQL

i'm trying to execute a query to give me 10 rows with the most biggest score ,column score in my table is a json object like :
{fa="7",en="7"}
how can i set my query to order by this json object ( it doesn't matter which of them (en or fa) used because they are always same )
Assuming your json is {"fa"="7","en"="7"} and assuming your json are in my_json_col column you could access using a -> operator and order by
SELECT *
from my_table
order by my_json_col->"fa"

can I compare with where two entire json values?

I have a JSON field in the stadiums table (mysql) named location, can i compare it with another json like below?...
select *from stadiums where location = '{"lat":40, "lng":3}';
*The query doesnt return me any error, but doesnt return me any row when there is in fact a coincidence
You can use CAST() function:
SELECT * FROM stadiums WHERE location = CAST('{"lat":40, "lng":3}' AS JSON);
MySQL has JSON_SEARCH JSON_CONTAINS JSON_EXTRACT functions that you can use to search JSON fields.
Try something like:
select * from stadiums where
JSON_EXTRACT(location, '$.lat') = 40 and
JSON_EXTRACT(location, '$.lng') = 3;