Postgreql avg on JSON query - json

I have this query that gives me a list of values from a JSON type column. Now I have two questions
Is this approach correct to access nested JSON elements?
How would I now get the average of my values?
select json_extract_path_text(json_extract_path(report_data, 'outer_key'), 'inner_key') as values
from report
where serial_number like '%123456%';

Given that inner_key is a number, you can simply cast it to a numeric type:
select avg((report_data->'outer_key'->>'inner_key')::float8)
from report
where serial_number like '%123456%';

Related

Snowflake latteral flatten data types

I have a table containing an id column and a json column(variant data type). I want to flatten the data, make the value column a variant, assign each value in the value column a data type if a condition is met, then eventually pivot the data and have each column be the correct data type.
Example code that doesn't work:
with cte as (
select
1 as id,
parse_json('{
"field1":"TRUE",
"field2":"some string",
"field3":"1.035",
"field4":"097334"
}') as my_output
)
select
id,
key,
to_variant(
case
when value in ('true', 'false') then value::boolean
when value like ('1.0') then value::decimal
else value::string
end) as value
from cte, lateral flatten(my_output)
Ultimately, I'd like to pivot the data and have a wide table with columns id, field1, field2, etc. where field1 is boolean, field2 is string, field3 is a decimal etc.
This is just a simple example, instead of 4 fields, I'm dealing with hundreds.
Is this possible?
For the pivot, I'm using dbt_utils.get_column_values to get the column names dynamically. I'd really prefer a solution that doesn't involve listing out the column names, especially since there are hundreds.
Since you'd have to define each column in your PIVOT statement, anyway, it'd probably be much easier to simply select each attribute directly and cast to the correct data type, rather than using a lateral flatten.
select
my_output.field1::boolean,
my_output.field2::string,
my_output.field3::decimal(5,3),
my_output.field4::string
from cte;
Alternatively, if you want this to be dynamically created, you could create a stored procedure that dynamically uses your json to create a view over your table that has this select in it.
Solution ended up being
select
id,
key,
ifnull(try_parse_json(value), value) as value_mod,
typeof(value_mod)
from cte, lateral flatten(my_output)
Leading zeros are removed so things like zip codes have to be accounted for.

Querying dynamic JSON fields for first non-null value in AWS Athena

I am storing event data in S3 and want to use Athena to query the data. One of the fields is a dynamic JSON field that I do not know the field names for. Therefore, I need to query the keys in the JSON and then use those keys to query for the first non-null for that field. Below is an example of the data stored in S3.
{
timestamp: 1558475434,
request_id: "83e21b28-7c12-11e9-8f9e-2a86e4085a59",
user_id: "example_user_id_1",
traits: {
this: "is",
dynamic: "json",
as: ["defined","by","the", "client"]
}
}
So, I need a query to extract the keys from the traits column (which is stored as JSON), and use those keys to get the first non-null value for each field.
The closest I could come was sampling a value using min_by, but this does not allow for me to add a where clause without returning null values. I will need to use presto's "first_value" option, but I cannot get this to work with the extracted JSON keys from the dynamic JSON field.
SELECT DISTINCT trait, min_by(json_extract(traits, concat('$.', cast(trait AS varchar))), received_at) AS value
FROM TABLE
CROSS JOIN UNNEST(regexp_extract_all(traits,'"([^"]+)"\s*:\s*("[^"]+"|[^,{}]+)', 1)) AS t(trait)
WHERE json_extract(traits, concat('$.', cast(trait AS varchar))) IS NOT NULL OR json_size(traits, concat('$.', cast(trait AS varchar))) <> 0
GROUP BY trait
It's not clear to me what you expect as result, and what you mean by "first non-null value". In your example you have both string and array values, and none of them is null. It would be helpful if you provided more examples and also expected output.
As a first step towards a solution, here's a way to filter out the null values from traits:
If you set the type of the traits column to map<string,string> you should be able to do something like this:
SELECT
request_id,
MAP_AGG(ARRAY_AGG(trait_key), ARRAY_AGG(trait_value)) AS trait
FROM (
SELECT
request_id,
trait_key,
trait_value
FROM some_table CROSS JOIN UNNEST (trait) AS t (trait_key, trait_value)
WHERE trait_value IS NOT NULL
)
However, if you want to also filter values that are arrays and pick out the first non-null value, that becomes more complex. It could probably be done with a combination of casts to JSON, the filter function, and COALESCE.

How to search for value in array using mysql?

I have a column which stores values in array form like below
table_name : records
column_name : data sample
row 1 : ['John','Adam', 'Mike']
I am trying to apply query something like below
SELECT * FROM records WHERE data IN('Adam');
which is giving 0 results found.
The IN clause with one parameter is essentially the same as WHERE data = 'Adam', wich search for the exact value.
Since your row contains a different string from Adam, no results are returned.
The query for your situation should be something like this:
SELECT * FROM records WHERE data LIKE '%Adam%';
If you using JSONArray , you can try query using JSON_CONTAINS() function.
you can query like below:-
SELECT * FROM records WHERE JSON_CONTAINS(data, '[Adam]');
where data is column which contains the array.

Select max is returning a wrong value in MySQL

I have above table and I want to get the highest value from table bids where bid_id=60 using the following query
SELECT MAX(offer_amount) as maz FROM bids WHERE bid_id = 60
The problem is I'm getting the result as 80 in instead of the correct value which is 7000000
Anybody with an idea of how to solve this?
Store offer_amount in a numeric field (such as integer or decimal), not as text. Quick solution is to use the CAST() function in the query to cast the field's data type to a numeric one.

Converting date field to return only Day field

I am working for a POS company, i have a query in my program that gets date from multiple tables and one of the fields it returns is a date field that returns the the date in the format yyyy-mm-dd. Is there a way to get my query to bring this date field in the form 'dd'? if yes how?
You are looking for the date_format() function (see here):
select date_format(<datefield>, '%d');
This returns the value as a string. If you want it as a number, just use day():
select day(<datefield>)
You are looking for this:-
EXTRACT(unit FROM date)
or try this:-
SELECT DAY(your_date_field) AS dtDay FROM your_table
select DATE_FORMAT(your_date_column,' %d ') FROM your_table
As you mentioned Delphi, why not a Delphi solution:
open the query in a dataset
get the corresponding field
get the value with AsDateTime
use function DayOf from System.DateUtils to retreive the day
in case you need a dataset field for that, create a calulated field
move the day calculation into the OnCalcFields event of the dataset
There might still be plenty of other ways to do it.