Check if JSON value empty in MySQL? - mysql

Imagine a table which tracks baseball pitchers like so...
+------------+--------------------+-------+
| id | name | secondary_pitch |
+------------+--------------------+-------+
| 13 | Chris Sale | ['Curveball','Slider'] |
| 14 | Justin Verlander | ['Fastball','Changeup'] |
| 15 | CC Sabathia | ['Fastball','Curveball'] |
| 16 | Sonny Grey | ['Slider'] |
| 17 | Aldoris Chapman | [] |
+------------+--------------------+-------+
Notice the secondary_pitch column has a JSON value. So if a pitcher, like Chapman, has no secondary pitch, it will not return null, instead it returns an empty JSON string ('[]').
How then can I get a count of the number of pitchers who have no secondary pitch?
I can't do...
select count(*) from pitchers where secondary_pitch is null

I think you can just use json_length():
where json_length(secondary_pitch) = 0

You could use JSON_EXTRACT to get first value from your column and check for not null
where JSON_EXTRACT(`secondary_pitch`, '$[0]') is not null
Demo

I see this is not answering original question of matching against empty array ([]) but this has worked for me, matching against empty dictionary ({}), at mysql 5.7.20-0ubuntu0.16.04.1 - (Ubuntu).
I used JSON_OBJECT function but it is very likely the JSON_ARRAY will also work in similar way, creating the 'empty' object when called without arguments.
If I wanted to match against the json column vmkeys value of {} (empty dictionary), I used the following query:
SELECT vmkeys FROM `labinstances` WHERE vmkeys=JSON_OBJECT()
To match against the vmkeys value of NULL, I used this:
SELECT vmkeys FROM `labinstances` WHERE vmkeys is NULL
Hope this helps...

This will check where secondary_pitch is (null) or '' (empty string)
SELECT count(*) from pitchers WHERE secondary_pitch IS NULL OR secondary_pitch = '';
also you can use like this.
SELECT count(*) from pitchers WHERE secondary_pitch LIKE '%[]%'

You can use the below function
SELECT * FROM TABLE_NAME WHERE
JSON_SEARCH(secondary_pitchers, 'all', '')
IS NOT NULL;

Related

How to loop through an array in SQL where clause?

I have a MySQL table which has the following columns and records:
| Name | Total | GivenBy |
| ---- | -------- | ------------ |
| Z | 200 |['A','B','C'] |
| X | 240 |['A','D','C'] |
I would like to extract Record No. 1 on the basis of 3rd column where the SQL query would be like:
SELECT * FROM mytable WHERE GivenBy='B';
Is there a way I can loop through the list in third column and take out the respective string as required in the SQL WHERE clause in a single query?
Please note that I cannot add more columns in the table.
If you can please provide the query as MySQL compatible, I would really appreciate it.
The "array" you show isn't quite valid JSON, but if you use double-quotes instead of single-quotes, you can use JSON_TABLE() to do this:
CREATE TABLE MyTable
(
Name CHAR(1) PRIMARY KEY,
Total INT NOT NULL,
GivenBy JSON NOT NULL
);
INSERT INTO MyTable VALUES
('Z', 200, '["A","B","C"]'),
('X', 240, '["A","D","C"]');
SELECT Name, Total, g.Value
FROM MyTable
CROSS JOIN JSON_TABLE(GivenBy, '$[*]' COLUMNS(Value CHAR(1) PATH '$')) AS g;
+------+-------+-------+
| name | total | value |
+------+-------+-------+
| X | 240 | A |
| X | 240 | D |
| X | 240 | C |
| Z | 200 | A |
| Z | 200 | B |
| Z | 200 | C |
+------+-------+-------+
But the best choice is not to store "arrays" in MySQL. Store the values one per row in a second table.
You can use the "like" keyword with regex to match your requirements in the third column.
select * from table where givenBy like "%B%";
Something similar would work.
You need to run a script:
Retrieve the list of unique values in the GivenBy column using the following query:
SELECT DISTINCT JSON_EXTRACT(GivenBy, '$[*]') AS GivenByValues
FROM mytable;
Loop through the list of unique values, and for each value, run a query that uses that value in the WHERE clause:
SELECT *
FROM mytable
WHERE JSON_SEARCH(GivenBy, 'one', [current_value_from_loop]) IS NOT NULL;

Looping through an array in SQL column

I have a SQL table that looks something like this:
| ID | Value |
| --- | ----------------------------------------------------- |
| 1 | {"name":"joe", "lastname":"doe", "age":"34"} |
| 2 | {"name":"jane", "lastname":"doe", "age":"29"} |
| 3 | {"name":"michael", "lastname":"dumplings", "age":"40"}|
How can I using SQL select function, select only the rows where "age" (in value column) is above 30?
Thank you.
The column Value as it is it contains valid JSON data.
You can use the function JSON_EXTRACT() to get the the age and convert it to a numeric value by adding 0:
SELECT *
FROM tablename
WHERE JSON_EXTRACT(Value, "$.age") + 0 > 30;
See the demo.

How to change the data row 1 equal to row 2 if the row 1 is null?

How to change data of PAYMENTDATE equal to the data of CREATIONDATE whenever the data of PAYMENTDATE is NULL? For example:
+-------------+--------------+
| PAYMENTDATE | CREATIONDATE |
+-------------+--------------+
| 2018-03-21 | 2018-03-01 |
| NULL | 2018-04-05 |
| NULL | 2018-07-06 |
| 2018-09-12 | 2018-08-23 |
| 2018-12-13 | 2018-11-21 |
+-------------+--------------+
Here is the my query:
SELECT
details.PAYMENTDATE,
account.CREATIONDATE
FROM
account
INNER JOIN
details ON account.DETAILSKEY = details.PRIMARYKEY
I've tried using
IF(details.PAYMENTDATE IS NULL,
details.PAYMENTDATE = account.CREATIONDATE,
details.PAYMENTDATE = details.PAYMENTDATE) AS NULLDATA,
But it does not work. Thank you for your help.
You don't need to set the value inside IF statement.
IF(details.PAYMENTDATE IS NULL, account.CREATIONDATE, details.PAYMENTDATE) AS NULLDATA
You can also use COALESCE
COALESCE(details.PAYMENTDATE, account.CREATIONDATE) AS NULLDATA
Use COALESCE:
SELECT
COALESECE(d.PAYMENTDATE, a.CREATIONDATE) AS PAYMENTDATE
a.CREATIONDATE
FROM account a
INNER JOIN details d
ON a.DETAILSKEY = d.PRIMARYKEY
The COALESCE function works by replacing the first argument with the second argument in the event that the first argument be NULL, so in
COALESCE(NULL, 3)
would return 3, but COALESCE(3, 5) would return 3.
I think that the problem is in the if because you assign the value of null in the first return value of your if
details.PAYMENTDATE = account.CREATIONDATE
Your code should be this way
SELECT
details.PAYMENTDATE,
IF(f.paymentdate IS NULL,
f.CREATIONDATE,
f.CREATIONDATE) AS NULLDATA,
account.CREATIONDATE
FROM
account
INNER JOIN
details ON account.DETAILSKEY = details.PRIMARYKEY
Just returning the desired values not assign the others.
I hope my explanation was good (no native speaker)

MySQL query to concat prefix to existing value in a field

My table structure is as follows,
ID Name Source
1 John first.jpg
2 Doe second.jpg
3 Mary third.jpg
4 Kurian four.jpg
I would like to update the "Source" by prepending with the host and primary key as follows
http://example.com/1/first.jpg
http://example.com/2/second.jpg
http://example.com/3/third.jpg
http://example.com/4/four.jpg
tried with CONCAT("http://example.com/"+id,Source) but fails with Truncated incorrect DOUBLE value:
Any suggestion will be greatly apreciated.
Try
UPDATE table_name
SET Source = CONCAT('http://example.com/', ID, '/', Source);
Result
| ID | Name | Source |
|----|--------|---------------------------------|
| 1 | john | http://example.com/1/first.jpg |
| 2 | Doe | http://example.com/2/second.jpg |
| 3 | Mary | http://example.com/3/third.jpg |
| 4 | Kurian | http://example.com/4/fourth.jpg |
checkout this
SELECT CONCAT("http://example.com/" , CONCAT(ID , CONCAT("/" , Source))) FROM table_name;
or simply
SELECT CONCAT("http://example.com/" ,ID , "/" , Source) FROM table_name;
You can iterate in sql but the easiest way is to create a php script in which you create an array with the rows of the table
Then use the dot si tax to concat ID with the domain name and the source, something like:
$newval = ‘{$table[“ID”]}’ .“/Domainname.com/” . ’{$table[“Source”]}’;
Where $table is a variable storing the associative array of the table
And then make a new query in which you override the source column for each row in the table array
Please try below code:
UPDATE table_Name
SET Source = concat(concat(CONCAT('http://example.com/',ID),'/'),source);

MySQL Subselect issue

I have an issue with a mysql subselect.
**token table:**
id | token | articles
1 | 12345 | 7,6
2 | 45saf | 6,7,8
**items table:**
id | name | filename
6 | Some brilliant name | /test/something_useful.mp3
7 | homer simpson | /test/good-voice.mp3
**query:**
SELECT items.`filename`,items.`name` FROM rm_shop items WHERE items.`id` IN ( SELECT token.`articles` FROM rm_token token WHERE token.`token` = 'token')
I only get one of the two files (with the id 7 that is). What am I missing here?
For a column with concatenated data (like your "articles" column), you can not use MySQL IN() Function. Instead use the string function FIND_IN_SET() to query such values. In your case:
SELECT items.`filename`,items.`name` FROM rm_shop items
WHERE FIND_IN_SET(items.`id`,
(SELECT token.`articles` FROM rm_token token WHERE token.`token` = 'token')) > 0
A working sqlfiddle: http://sqlfiddle.com/#!2/796998/3/0