Select where json contains - json

I have a postgres table:
Column | Type
------------------+------------------------+
id | bigint |
foo_id | integer |
foo_name | character varying(255) |
bar_id | json |
With values
id | foo_id | foo_name | bar_id
--------+----------------+-------------------------------+----------------------------
17 | 717639 | name 1 | [910, 5383774, 437, 5350]
18 | 8442028 | name 2 | [7274, 6241861, 437, 73669939]
19 | 77415 | name n | [7274, 5513, 249642574, 743181502]
How can I select from this table records ids where bar_id contains value 437?

You can use the operator #> to check if the array contains a specific value.
However that only works with jsonb values, not json values. So you need to cast your column.
select *
from the_table
where bar_id:jsonb #> '[437]';
It would be better to change the column's type to jsonb.

Related

Disable MySQL to convert string to 0 [duplicate]

I came across this auto typecasting of MYSQL from String to Integer seems to me weird.
mysql> select * from `isps` where `id` = '3ca6fb49-9749-3099-b30d-19ce56349ad6' OR `unique_id` = '3ca6fb49-9749-3099-b30d-19ce56349ad6';
+----+--------------------------------------+---------------+--------------+---------------------+---------------------+
| id | unique_id | name | code | created_at | updated_at |
+----+--------------------------------------+---------------+--------------+---------------------+---------------------+
| 3 | ee8db3be-1bf7-3440-8add-37232cfc4ecb | TTN | ttn | 2019-09-26 08:12:14 | 2019-09-26 08:12:14 |
| 7 | 3ca6fb49-9749-3099-b30d-19ce56349ad6 | ONE BROADBAND | onebroadband | 2019-09-26 08:12:14 | 2019-09-26 08:12:14 |
+----+--------------------------------------+---------------+--------------+---------------------+---------------------+
I had not expected result with id = 3 can anyone help with this.
DataType in my database
id - BIGINT
unique_id - varchar(200)
You can cast id to a string before comparing.
select * from `isps` where CAST(`id` AS CHAR) = '3ca6fb49-9749-3099-b30d-19ce56349ad6' OR `unique_id` = '3ca6fb49-9749-3099-b30d-19ce56349ad6';
Note that this will slow down the query significantly, since it won't be able to use the index on the id column.

Mysql: Order By with numerical value shows wrong order

I'm using Spring Boot 2.2.6.RELEASE. I have a repository method looks like this:
#Query(value = "SELECT m FROM Media m ORDER BY m.viewCount DESC")
Page<Media> findMedias(Pageable pageable);
I get unordered result list with this. I tried to run the next query in the cli:
SELECT media.view_count FROM mydb.media ORDER BY media.view_count DESC;
The result looks like this:
--------------
| 9 |
| 8 |
| 7 |
| 6 |
| 5 |
| 4 |
| 3 |
| 3 |
| 20 |
| 19 |
| 18 |
| 17 |
| 16 |
| 15 |
| 13 |
| 12 |
| 12 |
| 11 |
| 10 |
| 1 |
| 1 |
--------------
I want the value of 20 to be the first and not 9. Why MySQL do this kind of order? It shows one digit value first instead of the highest number?
EDIT:
I use sql file to create my tables. view_count column has LONG as type, not String. The query looks like this:
CREATE TABLE IF NOT EXISTS media(m_id INTEGER PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255) NOT NULL, category VARCHAR(10) NOT NULL, file_name VARCHAR(255) NOT NULL, view_count LONG NOT NULL, download_count LONG NOT NULL);
The view_count is stored as a string in your table which is not incorrect. If you can, then change it to integer. If you can not do that then, use the below to get the desired output.
SELECT m.view_count
FROM media m
ORDER BY CAST(m.view_count AS UNSIGNED) DESC;

How to calculate count of each value in MySQL JSON array?

I have a MySQL table with the following definition:
mysql> desc person;
+--------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | text | YES | | NULL | |
| fruits | json | YES | | NULL | |
+--------+---------+------+-----+---------+-------+
The table has some sample data as follows:
mysql> select * from person;
+----+------+----------------------------------+
| id | name | fruits |
+----+------+----------------------------------+
| 1 | Tom | ["apple", "orange"] |
| 2 | John | ["apple", "mango"] |
| 3 | Tony | ["apple", "mango", "strawberry"] |
+----+------+----------------------------------+
How can I calculate the total number of occurrences for each fruit? For example:
+------------+-------+
| fruit | count |
+------------+-------+
| apple | 3 |
| orange | 1 |
| mango | 2 |
| strawberry | 1 |
+------------+-------+
Some research shows that the JSON_LENGTH function can be used but I cannot find an example similar to my scenario.
You can use JSON_EXTRACT() function to extract each value ("apple", "mango", "strawberry" and "orange") of all three components of the arrays, and then then apply UNION ALL to combine all such queries:
SELECT comp, count(*)
FROM
(
SELECT JSON_EXTRACT(fruit, '$[0]') as comp FROM person UNION ALL
SELECT JSON_EXTRACT(fruit, '$[1]') as comp FROM person UNION ALL
SELECT JSON_EXTRACT(fruit, '$[2]') as comp FROM person
) q
WHERE comp is not null
GROUP BY comp
Indeed If your DB's version is 8, then you can also use JSON_TABLE() function :
SELECT j.fruit, count(*)
FROM person p
JOIN JSON_TABLE(
p.fruits,
'$[*]' columns (fruit varchar(50) path '$')
) j
GROUP BY j.fruit;
Demo
You can't do it without first creating a table with one row per fruit.
CREATE TABLE allfruits (fruit VARCHAR(10) PRIMARY KEY);
INSERT INTO allfruits VALUES ('apple'), ('orange'), ('mango'), ('strawberry');
There is not a good way to generate this from the JSON.
Once you have that table, you can join it to the JSON and then use GROUP BY to count the occurrences.
SELECT fruit, COUNT(*) AS count
FROM allfruits
JOIN person ON JSON_SEARCH(person.fruits, 'one', fruit) IS NOT NULL
GROUP BY fruit;
Output:
+------------+-------+
| fruit | count |
+------------+-------+
| apple | 3 |
| mango | 2 |
| orange | 1 |
| strawberry | 1 |
+------------+-------+
Note that it will do a table-scan on the person table to find each fruit. This is pretty inefficient, and as your person table gets larger, it will become a performance problem.
If you want to optimize for this type of query, then you shouldn't use JSON to store an array of fruits. You should store data in a normalized way, representing the many-to-many relationship between persons and fruits with another table.
This is related to my answer to Is storing a delimited list in a database column really that bad?
I think the simplest solution would be to use JSON_TABLE function.
The query you need is
select ft.fruit, count(ft.fruit) from person,
json_table(
fruits,
'$[*]' columns(
fruit varchar(128) path '$'
)
) as ft
group by ft.fruit
;
You can find working example in this dbfiddle
Fruit demo

Convert Json to separate columns in HIVE

I have 4 columns in Hive database table. First two columns are of type string, 3rd and 4th are of JSON. Type. How to extract json data in different columns.
SERDE available in Hive seems to be handling only json data. I have both normal (STRING) and JSON data. How can I extract data in separate colums here.
Example:
abc 2341 {max:2500e0,value:"20",Type:"1",ProviderType:"ABC"} {Name:"ABC",minA:1200e0,StartDate:1483900200000,EndDate:1483986600000,Flags:["flag4","flag3","flag2","flag1"]}
xyz 6789 {max:1300e0,value:"10",Type:"0",ProviderType:"foo"} {Name:"foo",minA:3.14159e0,StartDate:1225864800000,EndDate:1225864800000,Flags:["foo","foo"]}
Given a fixed JSON
create table mytable (str string,i int,jsn1 string, jsn2 string);
insert into mytable values
('abc',2341,'{"max":2500e0,"value":"20","Type":"1","ProviderType":"ABC"}','{"Name":"ABC","minA":1200e0,"StartDate":1483900200000,"EndDate":1483986600000,"Flags":["flag4","flag3","flag2","flag1"]}')
,('xyz',6789,'{"max":1300e0,"value":"10","Type":"0","ProviderType":"foo"}','{"Name":"foo","minA":3.14159e0,"StartDate":1225864800000,"EndDate":1225864800000,"Flags":["foo","foo"]}')
;
select str,i
,jsn1_max,jsn1_value,jsn1_type,jsn1_ProviderType
,jsn2_Name,jsn2_minA,jsn2_StartDate,jsn2_EndDate
,jsn2_Flags
from mytable
lateral view json_tuple (jsn1,'max','value','Type','ProviderType')
j1 as jsn1_max,jsn1_value,jsn1_type,jsn1_ProviderType
lateral view json_tuple (jsn2,'Name','minA','StartDate','EndDate','Flags')
j2 as jsn2_Name,jsn2_minA,jsn2_StartDate,jsn2_EndDate,jsn2_Flags
;
+-----+------+----------+------------+-----------+-------------------+-----------+-----------+----------------+---------------+-----------------------------------+
| str | i | jsn1_max | jsn1_value | jsn1_type | jsn1_providertype | jsn2_name | jsn2_mina | jsn2_startdate | jsn2_enddate | jsn2_flags |
+-----+------+----------+------------+-----------+-------------------+-----------+-----------+----------------+---------------+-----------------------------------+
| abc | 2341 | 2500.0 | 20 | 1 | ABC | ABC | 1200.0 | 1483900200000 | 1483986600000 | ["flag4","flag3","flag2","flag1"] |
| xyz | 6789 | 1300.0 | 10 | 0 | foo | foo | 3.14159 | 1225864800000 | 1225864800000 | ["foo","foo"] |
+-----+------+----------+------------+-----------+-------------------+-----------+-----------+----------------+---------------+-----------------------------------+

mysql where type int

my table 'users' have a following schema
| id | name | class|
| 0 | John | Primary |
| 1 | Mary | Primary |
I tried this query:
select * from users where id = 'a'
The mysql return all rows from table.
How can I solve this problem?
If id is of type Integer, you have to type it without quotation marks. For example:
select * from users where id = 0;
should return:
| 0 | John | Primary
However, the 'a' in your example is not an Integer, so I am not 100 percent sure where this comes from and if I understood you correctly.