My MySQL table contain json column academics.
Table values look like this :
id academics
--------------------------------------------------------
100 ["CBSE-Afternoon-12-A","CBSE-Morning-12-B"]
200 ["CBSE-Afternoon-12-C","CBSE-Morning-12-D"]
300 ["CBSE-Afternoon-12-E","CBSE-Afternoon-12-F"]
I have to find the id from the above table based on the search key:
CBSE-Morning-12 & CBSE-Afternoon-12
I have tried the below query
SELECT id
FROM ACADEMIC_TABLE
WHERE JSON_SEARCH(academics, 'all', 'CBSE-Morning-12%') IS NOT NULL
it returns id: 100,200 correctly.
But I need to search with two keywords like condition in JSON
[CBSE-Morning-12 & CBSE-Afternoon-12 ] and return id 100,200,300
Please help me
I need to search with two keywords like condition in JSON [CBSE-Morning-12 & CBSE-Afternoon-12 ] and return id 100,200,300
Looking at the sample data - you need the value contained either first or second pattern. If so then you must use OR:
SELECT id
FROM ACADEMIC_TEBLE
WHERE JSON_SEARCH(academics, 'one', 'CBSE-Morning-12%') IS NOT NULL
OR JSON_SEARCH(academics, 'one', 'CBSE-Afternoon-12%') IS NOT NULL;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=bdc058111adf7d4200a1471c9873e94c
Related
I have the following json structure on my Postgres. The table is named "customers" and the field that contains the json is named "data"
{
customerId: 1,
something: "..."
list: [{ nestedId: 1, attribute: "a" }, { nestedId: 2, attribute: "b" }]
}
I'm trying to query all customers that have an element inside the field "list" with nestedId = 1.
I accomplished that poorly trough the query:
SELECT data FROM customers a, jsonb_array_elements(data->'list') e WHERE (e->'nestedId')::int = 1
I said poorly because since I'm using jsonb_array_elements on the FROM clausule, it is not used as filter, resulting in a seq scan.
I tried something like:
SELECT data FROM customers where data->'list' #> '{"nestedId": 1, attribute: "a"}'::jsonb
But it does not return anything. I imagine because the "list" field is seen as an array and not as each type of my records.
Any ideas how to perform that query filtering nestedId on the WHERE condition?
Try this query:
SELECT data FROM customers where data->'list' #> '[{"nestedId": 1}]';
This query will work in Postgres 9.4+.
I have a MySQL DB containing a table named "products".
This table contains a Json Data_type column named "values".
I would like to find the path to extract a specific value :
select JSON_EXTRACT(values, '$.COD')
from products
where id = '1'
returns :
"COD": {"<channels>": {"<locales>": "3699999999999"}}
And what I want is "3699999999999".
It is pretty obvious that my path is not the good one, but I can't find the solution.
Thanks for your help !
You can try
SELECT JSON_EXTRACT(`values`, '$.COD.<channels>.<locales>') FROM products WHERE id = '1';
For more details please refer mysql-for-your-json
If I have a table with a column named json_stuff, and I have two rows with
{ "things": "stuff" } and { "more_things": "more_stuff" }
in their json_stuff column, what query can I make across the table to receive [ things, more_things ] as a result?
Use this:
select jsonb_object_keys(json_stuff) from table;
(Or just json_object_keys if you're using just json.)
The PostgreSQL json documentation is quite good. Take a look.
And as it is stated in the documentation, the function only gets the outer most keys. So if the data is a nested json structure, the function will not return any of the deeper keys.
WITH t(json_stuff) AS ( VALUES
('{"things": "stuff"}'::JSON),
('{"more_things": "more_stuff"}'::JSON)
)
SELECT array_agg(stuff.key) result
FROM t, json_each(t.json_stuff) stuff;
Here is the example if you want to get the key list of each object:
select array_agg(json_keys),id from (
select json_object_keys(json_stuff) as json_keys,id from table) a group by a.id
Here id is the identifier or unique value of each row. If the row cannot be distinguished by identifier, maybe it's better to try PL/pgSQL.
Here's a solution that implements the same semantics as MySQL's JSON_KEYS(), which...:
is NULL safe (i.e. when the array is empty, it produces [], not NULL, or an empty result set)
produces a JSON array, which is what I would have expected from how the question was phrased.
SELECT
o,
(
SELECT coalesce(json_agg(j), json_build_array())
FROM json_object_keys(o) AS j (j)
)
FROM (
VALUES ('{}'::json), ('{"a":1}'::json), ('{"a":1,"b":2}'::json)
) AS t (o)
Replace json by jsonb if needed.
Producing:
|o |coalesce |
|-------------|----------|
|{} |[] |
|{"a":1} |["a"] |
|{"a":1,"b":2}|["a", "b"]|
Insert json_column and table
select distinct(tableProps.props) from (
select jsonb_object_keys(<json_column>) as props from <table>
) as tableProps
I wanted to get the amount of keys from a JSONB structure, so I'm doing something like this:
select into cur some_jsonb from mytable where foo = 'bar';
select into keys array_length(array_agg(k), 1) from jsonb_object_keys(cur) as k;
I feel it is a little bit wrong, but it works. It's unfortunate that we can't get an array directly from the json_object_keys() function. That would save us some code.
Datamodel
A person is represented in the database as a meta table row with a name and with multiple attributes which are stored in the data table as key-value pair (key and value are in separate columns).
Simplified data-model
Now there is a query to retrieve all users (name) with all their attributes (data). The attributes are returned as JSON object in a separate column. Here is an example:
name data
Florian { "age":25 }
Markus { "age":25, "color":"blue" }
Thomas {}
The SQL command looks like this:
SELECT
name,
json_object_agg(d.key, d.value) AS data,
FROM meta AS m
JOIN (
JOIN d.fk_id, d.key, d.value AS value FROM data AS d
) AS d
ON d.fk_id = m.id
GROUP BY m.name;
Problem
Now the problem I am facing is, that users like Thomas which do not have any attributes stored in the key-value table, are not shown with my select function. This is because it does only a JOIN and no LEFT OUTER JOIN.
If I would use LEFT OUTER JOIN then I run into the problem, that json_object_agg try's to aggregate NULL values and dies with an error.
Approaches
1. Return empty list of keys and values
So I tried to check if the key-column of a user is NULL and return an empty array so json_object_agg would just create an empty JSON object.
But there is not really a function to create an empty array in SQL. The nearest thing I found was this:
select '{}'::text[];
In combination with COALESCE the query looks like this:
json_object_agg(COALESCE(d.key, '{}'::text[]), COALESCE(d.value, '{}'::text[])) AS data
But if I try to use this I get following error:
ERROR: COALESCE types text and text[] cannot be matched
LINE 10: json_object_agg(COALESCE(d.key, '{}'::text[]), COALES...
^
Query failed
PostgreSQL said: COALESCE types text and text[] cannot be matched
So it looks like that at runtime d.key is a single value and not an array.
2. Split up JSON creation and return empty list
So I tried to take json_object_agg and replace it with json_object which does not aggregate the keys for me:
json_object(COALESCE(array_agg(d.key), '{}'::text[]), COALESCE(array_agg(d.value), '{}'::text[])) AS data
But there I get the error that null value not allowed for object key. So COALESCE does not check that the array is empty.
Qustion
So, is there a function to check if a joined column is empty, and if yes return just a simple JSON object?
Or is there any other solution which would solve my problem?
Use left join with coalesce(). As default value use '{}'::json.
select name, coalesce(d.data, '{}'::json) as data
from meta m
left join (
select fk_id, json_object_agg(d.key, d.value) as data
from data d
group by 1
) d
on m.id = d.fk_id;
name | data
---------+------------------------------------
Florian | { "age" : "25" }
Marcus | { "age" : "25", "color" : "blue" }
Thomas | {}
(3 rows)
I searched enough before posting it.
My table structure:
aid | bid | cid | did |
Where aid, bid together are the primary keys.
When I update the value of cid using a where clause for aid, bid I also want to get the did value of the updated row.
Something like this:
$this->db->set('cid', 1, FALSE)
->where(array(
'aid' => $a_id,
'bid' => $b_id
))
->update('my_table')
->select('did');
The above query says:
Fatal error: Call to a member function select() on a non-object in...
I tried this:
How to get ID of the last updated row in MySQL?
Which is like 3 queries.
I'd suggest fetching the values you're about to update, store their IDs in an array, and run an UPDATE with a WHERE id IN (1, 2, ...).
What you're trying to do is not supported by MySQL. You'll need to run at least 2 queries, and since you're fetching the values the first time and already know what values you're updating, then you can also recreate the new row and it's values without using a query after UPDATE.
In your given example:
$this->db->set('cid', 1, FALSE)
->where(array(
'aid' => $a_id,
'bid' => $b_id
))
->update('my_table')
->select('did');
set(), where() and also select() returns an object that builds on the query. However update() return a value which is the results and doesn't have a function called select() and not set() and where() for that matter.