Would appreciate if you can help a mariaDB newbie with this.
I have a mariaDB database table called 'brand' with data as below.
Datatypes are VARCHAR and JSON.
name varchar(255) NOT NULL
sold longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid('sold'))
name
sold
Test
[{"id":"0","name":"0","count":5000},{"id":"1","name":"1","count":5000}]
Test2
[{"id":"0","name":"0","count":10000},{"id":"1","name":"1","count":10000}]
Test3
[{"id":"0","name":"0","count":15000},{"id":"1","name":"1","count":35000}]
Test4
[{"id":"0","name":"0","count":700},{"id":"1","name":"1","count":600}]
When I execute the query:
SELECT name, JSON_EXTRACT(sold, '$[*].count') as cnt FROM brands;
SELECT name, JSON_EXTRACT(sold, '$**.count') as cnt FROM brands;
I get the below output
name
cnt
Test
[5000, 5000]
Test2
10000
Test3
15000
Test4
700
I was expecting output as below
name
cnt
Test
[5000, 5000]
Test2
[10000, 10000]
Test3
[15000, 35000]
Test4
[700, 600]
Can you please help me correct the error?
I have searched the mariaDB documentation https://mariadb.com/kb/en/json_extract/ but not able to find a solution yet.
I also looked at this post: How do I extract values from a JSON array in MariaDB or MySQL? and I am implementing same SQL...
Thank you!
Update: 25 Jan
Ticket submitted to JIRA mariadb and fixed here
Related
I have a table called test. there are several records that have unformatted SSNs (i.e. they are missing the dashes)
They are:
123456789
When I want them to be formatted like:
123-45-6789
I want to run a script that can insert in these 2 dashes for records like this that are strings with 9 characters.
If you need to update the rows you can use the following insert() string syntax to check its functionality:
with test as (
select '123456789' as ssn
)
select insert(insert(ssn,4,0,'-'),7,0,'-')
from test;
update test set ssn=insert(insert(ssn,4,0,'-'),7,0,'-')
where ssn not like '%-%';
It might be a better idea to leave the data as-is and add a generated column that implements the above insert syntax instead. This depends on the data, which you haven't shown us.
A solution that uses the regexp functions
update test
set SSN = regexp_replace(SSN, '([0-9]{3})([0-9]{2})([0-9]{4})$','\\1-\\2-\\3')
where SSN RLIKE '^[0-9]{9}$'
select * from test
| SSN |
| :---------- |
| 123-45-6789 |
db<>fiddle here
SELECT NULL; prints
<null>
SELECT CAST('0000-00-00' AS DATE); prints
<null>
SELECT NULL IS NULL; prints
1
SELECT CAST('0000-00-00' AS DATE) IS NULL; prints
0
Why isn't the result of the 4th statement 1?
Tested using DataGrip while connecting to MySQL 5.7.17 on windows.
Because the 2. isn't true:
SELECT CAST('0000-00-00' AS DATE); prints
0000-00-00
It doesn't print
NULL
4th statement show the result 0000-00-00
In mysql Only null is null. Everything else is not, so that it returns 1
Thanks to kiks73, iamsankalp89 and moscas for their answers (kiks73's answer - iamsankalp89's answer - moscas's answer) which helped me find the solution/ explanation for the odd behavior that I've encountered.
The reason for the odd behavior was how JDBC driver which is used by DataGrip would handle a zero date.
It would receive the date as zeros from the database then convert it to null.
That would result in DataGrip reading zero dates as nulls because of the JDBC conversion.
Howevenr, because its done at the JDBC layer (not the database layer) the database doesn't see those values as nulls.
To test for that, i ran the database connection and the query through mysql shell, which would print zeros instead of nulls.
Tested in Ubuntu mysql:
SELECT CAST('0000-00-00' AS DATE) ;
The value of the above query is null,
mysql> SELECT CAST('0000-00-00' AS DATE);
+----------------------------+
| CAST('0000-00-00' AS DATE) |
+----------------------------+
| NULL |
+----------------------------+
1 row in set, 1 warning (0.00 sec)
SELECT CAST('0000-00-00' AS DATE) IS NULL;
In the above query, you are trying to check the value is null using IS NULL function and the answer is True so only it's displaying the value as 1.
mysql> SELECT CAST('0000-00-00' AS DATE) IS NULL;
+------------------------------------+
| CAST('0000-00-00' AS DATE) IS NULL |
+------------------------------------+
| 1 |
+------------------------------------+
1 row in set, 1 warning (0.00 sec)
While testing using others,
SELECT CAST('0000-00-00' AS DATE) ;
The value of the above query won't display as NULL,
SELECT CAST('0000-00-00' AS DATE) IS NULL;
The result of above query is False, so only it displays as 0
I'm storing permissions into DB with Array JSON String, and i want select them by permission specific permission. at this time I'm selecting them like this:
1 | Dog | [3,4]
2 | Cat | [33,4]
3 | Tiger | [5,33,4]
4 | wolf | [3,5]
SELECT * FROM `pages` WHERE access REGEXP '([^"])3([^"])'
it works but not as it should work. This query gives me all records which contains 3 but also it gives which contains 33. my question is how i must format my regexp to get row by specific value into json string.
p.s i have mysql 5.5 so as i know on this version json functions is not supported
If you only have numbers in the fields, you can alter your regexp to only take values where the string you are looking for (here the '3') does not have another number immediately close to it :
SELECT * FROM `pages` WHERE access REGEXP '([^"0-9])3([^"0-9])'
REGEXP '[[:<:]]3[[:>:]]'
That is, use the "word boundary" thingies.
The following query returns 0.000 when I expected it to return 0.
SELECT IFNULL(TRUNCATE(NULL, 3), 0) FROM DUAL
Why is that?
Breaking it apart works as expected and described in the TRUNCATE function documentation and IFNULL docs :
SELECT TRUNCATE(NULL, 3) FROM DUAL
returns null.
SELECT IFNULL(null, 0) FROM DUAL
this returns 0. So why do I get 0.000 when nesting them?
The type of TRUNCATE(NULL,n) is DOUBLE. This can be seen by running mysql with the --column-type parameter:
$mysql -u root --column-type testdb
mysql> SELECT(TRUNCATE(NULL,3));
Field 1: `(TRUNCATE(NULL,3))`
Catalog: `def`
Database: ``
Table: ``
Org_table: ``
Type: DOUBLE
Collation: binary (63)
Length: 20
Max_length: 0
Decimals: 3
Flags: BINARY NUM
+--------------------+
| (TRUNCATE(NULL,3)) |
+--------------------+
| NULL |
+--------------------+
1 row in set (0,00 sec)
According to the IFNULL documentation page:
The default result value of IFNULL(expr1,expr2) is the more “general” of the two expressions, in the order STRING, REAL, or INTEGER
Therefore your result is 0.000, the 0 as DOUBLE truncated to 3 decimal places.
Your expectation is wrong. TRUNCATE(NULL, 3) is going to return a decimal value with three decimal places. Although the value is NULL, NULL has a type associated with it. The type is integer by default. But this is not a default situation.
So, 0 is converted to a decimal with three decimal places.
EDIT:
To understand what I mean, consider this code:
create table t as
select truncate(NULL, 3) as x;
describe t;
You will see that the column has a precision of "3". The NULL value is not typeless. You can see this on SQL Fiddle.
I am developing a system using MySQL queries written by another programmer, and am adapting his code.
I have three questions:
1.
One of the queries has this select statement:
SELECT
[...]
AVG(mytable.foo, 1) AS 'myaverage'`,
Is the 1 in AVG(mytable.foo, 1) AS 'myaverage' legitimate? I can find no documentation to support its usage?
2.
The result of this gives me average values to 2 decimal places, why?.
3.
I am using this to create a temp table. So:
(SELECT
[...]
AVG(`mytable`.`foo`, 1) AS `myaverage`,
FROM
[...]
WHERE
[...]
GROUP BY
[...])
UNION
(SELECT
[...]
FROM
[...]
WHERE
[...]
GROUP BY
[...])
) AS `tmptable`
ORDER BY
`tmptable`.`myaverage` DESC
When I sort the table on this column I get output which indicates that this average is being stored as a string, so the result is like:
9.3
11.1
In order to get around this what should I use?
Should I be using CAST or CONVERT, as DECIMAL (which I read is basically binary), BINARY itself, or UNSIGNED?
Or, is there a way to state that myaverage should be an integer when I name it in the AS statement?
Something like:
SELECT
AVG(myaverage) AS `myaverage`, INT(10)
Thanks.
On your last question: can you post the exact MySQL query that you are using?
The result type of a column from a UNION is determined by everything you get back. See http://dev.mysql.com/doc/refman/5.0/en/union.html .
So, even if your AVG() function returns a DOUBLE, the other part of the UNION may still return a string. In which case the column type of the result will be a string.
See the following example:
mysql> select a from (select 19 as a union select '120') c order by a;
+-----+
| a |
+-----+
| 120 |
| 19 |
+-----+
2 rows in set (0.00 sec)
mysql> select a from (select 19 as a union select 120) c order by a;
+-----+
| a |
+-----+
| 19 |
| 120 |
+-----+
2 rows in set (0.00 sec)
Just for anyone who's interested, I must have deleted or changed my predecessors code so this AVG question was incorrect. The correct code was ROUND(AVG(myaverage),1). Apologies to those who scrathed their heads over my stupidity.
on 1.
AVG() accepts exactly one argument, otherwise MySQL will raise an error:
mysql> SELECT AVG( id, 1 ) FROM anytable;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' 1 )' at line 1
http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html#function_avg
Just because I'm curious - what should the second argument do?