My table:
ID | something1 | something2 | ...
1 | meow | 5 |
2 | 4 | KITTIES |
Is there any way to select data as JSON in format {"1":{"something1":"meow","something2":5},"2":{...}}?
If you don't mind repeating the ID field in the JSON representation of a row, you can do:
SELECT
format('{%s}',
string_agg(
format(
'%s:%s',
to_json(ID::text),
row_to_json(my_table)
), ','
), ''
)::json as json_object
FROM my_table;
This gives you a JSON object containing a sub-object for each row in the table, keyed by the value in the ID field.
SQLFiddle
See this question for more details.
You can use this library to get an API of the database. Then, consume it! This is the fastest and clearest thing I can imagine.
Related
I have this type of string
'160f7a4a-766a-4c23-a155-8bd3f7389f77\', \'63233bfc-b663-4c73-890b-00a48d79c4dc'
In one column and I want like
'160f7a4a-766a-4c23-a155-8bd3f7389f77','63233bfc-b663-4c73-890b-00a48d79c4dc'
This type of result in MySQL
i have to perform query like
SELECT * FROM kapp_staging.kols where `kol_id` in (select REPLACE(json_id,'\'',"'") FROM kapp_staging.news_items
where `id` = '991'))
in where in clause i have subquery and in subquery
i geting
'160f7a4a-766a-4c23-a155-8bd3f7389f77\', \'63233bfc-b663-4c73-890b-00a48d79c4dc'
this type of value
so i need to remove \ from value so my where in query work fine.
i have data like:
Kols table
| id | kol_id | name | data |
|----|---------------------------------------- |---------| ------|
| 1 |160f7a4a-766a-4c23-a155-8bd3f7389f77 | balwant | data |
| 2 |63233bfc-b663-4c73-890b-00a48d79c4dc | vikram | data |
news items
| id | json_id | data |
|----|-----------------------------------------------------------------------------------------|---------|
| 991 | {'\160f7a4a-766a-4c23-a155-8bd3f7389f77\','\160f7a4a-766a-4c23-a155-8bd3f7389f77\'} | data |
I tried many ways but didn't get this response.
Thanks in Advance : )
The backslashes aren't in the data, they're just used to escape the quotes when inserting into the table. So you don't need to remove them.
However, you can't use IN to match values in a comma-delimited list, you need to use FIND_IN_SET(); see Search with comma-separated value mysql
You also need to remove the quotes and curly braces before you can use FIND_IN_SET().
SELECT DISTINCT k.*
FROM kols AS k
JOIN news_items AS n
ON FIND_IN_SET(k.kol_id,
REPLACE(REPLACE(REPLACE(json_id, '{', ''), '}', ''), "'", ''))
DEMO
Things would be much easier if you normalized your data and put the list of IDs into a separate table with one row per ID.
I have a table with a json column that contains an array of objects, like the following:
create table test_json (json_id int not null primary key, json_data json not null) select 1 as json_id, '[{"category":"circle"},{"category":"square", "qualifier":"def"}]' as json_data union select 2 as json_id, '[{"category":"triangle", "qualifier":"xyz"},{"category":"square"}]' as json_data;
+---------+----------------------------------------------------------------------------------------+
| json_id | json_data |
+--------------------------------------------------------------------------------------------------+
| 1 | [{"category":"circle"}, {"category":"square", "qualifier":"def"}] |
| 2 | [{"category":"triangle", "qualifier":"xyz"}, {"category":"square"}] |
+---------+----------------------------------------------------------------------------------------+
I'd like to be able to query this table to look for any rows (json_id's) that contain a json object in the array with both a "category" value of "square" and no "qualifier" property.
The sample table above is just a sample and I'm looking for a query that would work over hundreds of rows and hundreds of objects in the json array.
In MySQL 8.0, you would use JSON_TABLE() for this:
mysql> select json_id, j.* from test_json, json_table(json_data, '$[*]' columns (
category varchar(20) path '$.category',
qualifier varchar(10) path '$.qualifier')) as j
where j.category = 'square' and j.qualifier is null;
+---------+----------+-----------+
| json_id | category | qualifier |
+---------+----------+-----------+
| 2 | square | NULL |
+---------+----------+-----------+
It's not clear why you would use JSON for this at all. It would be better to store the data in the normal manner, one row per object, with category and qualifier as individual columns.
A query against normal columns is a lot simpler to write, and you can optimize the query easily with an index:
select * from mytable where category = 'square' and qualifier is null;
I found another solution using only MySQL 5.7 JSON functions:
select json_id, json_data from test_json
where json_extract(json_data,
concat(
trim(trailing '.category' from
json_unquote(json_search(json_data, 'one', 'square'))
),
'.qualifier')
) is null
This assumes the value 'square' only occurs as a value for a "category" field. This is true in your simple example, but I don't know if it will be true in your real data.
Result:
+---------+------------------------------------------------------------------------+
| json_id | json_data |
+---------+------------------------------------------------------------------------+
| 2 | [{"category": "triangle", "qualifier": "xyz"}, {"category": "square"}] |
+---------+------------------------------------------------------------------------+
I still think that it's a CodeSmell anytime you reference JSON columns in a condition in the WHERE clause. I understood your comment that this is a simplified example, but regardless of the JSON structure, if you need to do search conditions, your queries will be far easier to develop if your data is stored in conventional columns in normalized tables.
Your request is not clear. Both of your SQL records has not such properties but your JSON object has. Maybe you try to find any record that has such object. So the following is your answer:
create table test_json (json_id int not null primary key, json_data json not null) select 1 as json_id, '[{"category":"circle", "qualifier":"abc"},{"category":"square", "qualifier":"def"}]' as json_data union select 2 as json_id, '[{"category":"triangle", "qualifier":"xyz"},{"category":"square"}]' as json_data;
select * from test_json;
select * from test_json where 'square' in (JSON_EXTRACT(json_data, '$[0].category'),JSON_EXTRACT(json_data, '$[1].category'))
AND (JSON_EXTRACT(json_data, '$[0].qualifier') is NULL || JSON_EXTRACT(json_data, '$[1].qualifier') is NULL);
See Online Demo
Also see JSON Function Reference
I'm still pretty new to handling JSON fields in MySQL. All the solutions I've come across deal with objects that have key/values; unable to find one that handles JSON arrays.
Anyways, what I want to do is to be able to select all rows where the interestIds contain 2 in them. How do I do that? Thanks.
Users table
+----+-------------+
| id | interestIds |
+----+-------------+
| 1 | [1, 2] |
| 2 | [3, 2] |
| 3 | [2, 4] |
+----+-------------+
Sample test query:
SET #userId = 2;
SELECT * FROM Users
WHERE #userId IN JSON_CONTAINS(#user, interestIds, '$[1]');
I am confused as how to use the JSON_* functions; not sure what to put for the 3rd parameter...
You can use the following solution, using JSON_CONTAINS:
SELECT *
FROM Users
WHERE JSON_CONTAINS(interestIds, '2') = 1;
The third (optional) paramater path gives you the posibility to use this function only on a specific part of your JSON value. So the following example checks if 2 is the second value of the array:
SELECT *
FROM test
WHERE JSON_CONTAINS(interestIds, '2', '$[1]') = 1;
demo on dbfiddle.uk
Use JSON_SEARCH which returns path to element you are searching, or null if not found:
SELECT *
FROM users
WHERE JSON_SEARCH(interestids, 'one', '2') IS NOT NULL
Live Demo
If you're storing many-to-many relationship using simple JSON array, there are better ways to do it. Consider creating user_interest table and doing it the right and simpler way. That is if your JSON actually looks like you have shown us and does not contain dynamic key-value pairs.
SQL> select id
from users
where JSON_CONTAINS(interestIds, "2","$");
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
+----+
3 rows in set (0.0015 sec)
Wrap your select to JSON_ARRAYAGG
Like:
SELECT JSON_ARRAYAGG(JSON_OBJECT(....)) FROM table....
I am trying to separate a row to several rows with unique question reference by get_json_object in Hive, Can I do it by this way?
I just touch get_json_object in Hive, trying to separate a row to several rows with unique question reference (which is from one json format column), and contain other column information.
SELECT reference AS item_reference,
get_json_object(questions, '$.reference') AS question_reference,
get_json_object(questions, '$.type') AS question_type
from sandbox.exportitems limit 10;
For example, given the input:
reference | questions
NP002_025 | [{"reference":"3dfc54c0","type":"clozeformula"}]
DP001_1_10 | [{"reference":"73879547","type":"imageclozeformula"},
{"reference":"466a5b88","type":"clozedropdown"}]
The expected output is:
reference | questions_reference | questions_type
NP002_025 | 3dfc54c0 | clozeformula
DP001_1_10 | 73879547 | imageclozeformula
DP001_1_10 | 466a5b88 | clozedropdown
OK, as below is an example:
with core as (
SELECT
'DP001_1_10' as reference,
explode(
split(
regexp_replace(
regexp_replace(
regexp_replace('[{"reference":"73879547","type":"imageclozeformula"},{"reference":"466a5b88","type":"clozedropdown"}]', '\\]','')
,'\\}\\,\\{','\\}\\;\\{')
,'\\[','')
,'\\;')
) as json_str
)
select
reference,
get_json_object(json_str,'$.reference') as questions_reference,
get_json_object(json_str,'$.type') as questions_type
from
core;
+-------------+----------------------+--------------------+--+
| reference | questions_reference | questions_type |
+-------------+----------------------+--------------------+--+
| DP001_1_10 | 73879547 | imageclozeformula |
| DP001_1_10 | 466a5b88 | clozedropdown |
+-------------+----------------------+--------------------+--+
You can just replace the example strings 'DP001_1_10' and '[{"reference":"73879547","type":"imageclozeformula"},{"reference":"466a5b88","type":"clozedropdown"}]' to your column name of reference and questions.
So the final hql you want maybe like below:
with core as (
select
reference,
explode(
split(
regexp_replace(
regexp_replace(
regexp_replace(questions, '\\]','')
,'\\}\\,\\{','\\}\\;\\{')
,'\\[','')
,'\\;')
) as json_str
from
sandbox.exportitems
)
select
reference,
get_json_object(json_str,'$.reference') as questions_reference,
get_json_object(json_str,'$.type') as questions_type
from
core;
I am using MySQL, and I have a function which will accept a col data from a table row, and return a table-valued function. for example, a function like this:
CREATE FUNCTION [dbo].[wordlongerthan4](
#input text
) returns #result table(
pos int,
word varchar,
)
which will return the word longer than 4char and its position.
i want to do a sql something like below
select t.name,wordlongerthan4(t.content) from sometable as t;
on table
------------------------------------------------------------------
| id | name | content |
------------------------------------------------------------------
|1 | my1 | i love something and nothing |
|2 | my2 | It is a sunny day today |
to get the result:
|name | pos | word |
--------------------------------
|my1 |8 |something |
|my1 |22 |nothing |
|my2 |9 |sunny |
|my2 |20 |today |
How could i write the sql?(the function wordlongerthan4 is already there,i only need the sql!)
What you are talking about doing is:
Looping through each record and extracting the content.
Splitting the content by a delimiter (space, in this case).
Measuring the length of each part
Adding the part to an array of successful results it its length < n
(4).
Returning the part, along with the original id and name from the
record it originally came from.
Like ajreal said, this is something that would best be done at the application layer, presumably inside of your php/java/whatever.
There is currently no built-in string explode/split function, but this question here might prove useful: Equivalent of explode() to work with strings in mysql.
You can (ab)use the new JSON_TABLE function in MySQL 8 to do this:
set #input = 'i love something and nothing';
SELECT Value, LENGTH(Value) as Length, LOCATE(Value, #delimited) as pos
FROM
JSON_TABLE(
CONCAT('["', REPLACE(#delimited, ' ', '", "'), '"]'),
"$[*]"
COLUMNS(
Value varchar(50) PATH "$"
)
) data
where LENGTH(Value) > 4;