How to pass binary (16) to a mysql function as an argument - mysql

I would like to pass the uuid of version varbinary(16) to a user-defined function in MySQL version 5.7.x - It throws an error
1406 - Data too long for column
I have a table with uuid primary key of type varbinary(16) - I would like to convert the binary(16) to human readable version so I written a function to convert the binary version.
CREATE DEFINER=`bala`#`localhost`
FUNCTION `bin_to_uuid`(`uuid` BINARY(32))
RETURNS varchar(32) CHARSET latin1
NO SQL
return LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
))
SELECT bin_to_uuid((UNHEX(REPLACE(uuid(), "-",""))))
MySQL version 5.7.x

The return type is varchar(32), but with the hyphens added, the text you're returning is 36 chars long.
Change the return type to varchar(36).

Related

Calculate the number of jobs reviewed per hour per day for November 2020?

This question is really confusing me. They didn't provide enough details of it. Whatever they have provided I have written below.
job_id: unique identifier of jobs
actor_id: unique identifier of actor
event: decision/skip/transfer
language: language of the content
time_spent: time spent to review the job in seconds
org: organization of the actor
ds: date in the yyyy/mm/dd format. It is stored in the form of text and we use presto to run. no need for date function
CREATE TABLE job_data
(
ds DATE,
job_id INT NOT NULL,
actor_id INT NOT NULL,
event VARCHAR(15) NOT NULL,
language VARCHAR(15) NOT NULL,
time_spent INT NOT NULL,
org CHAR(2)
);
INSERT INTO job_data (ds, job_id, actor_id, event, language, time_spent, org)
VALUES ('2020-11-30', 21, 1001, 'skip', 'English', 15, 'A'),
('2020-11-30', 22, 1006, 'transfer', 'Arabic', 25, 'B'),
('2020-11-29', 23, 1003, 'decision', 'Persian', 20, 'C'),
('2020-11-28', 23, 1005,'transfer', 'Persian', 22, 'D'),
('2020-11-28', 25, 1002, 'decision', 'Hindi', 11, 'B'),
('2020-11-27', 11, 1007, 'decision', 'French', 104, 'D'),
('2020-11-26', 23, 1004, 'skip', 'Persian', 56, 'A'),
('2020-11-25', 20, 1003, 'transfer', 'Italian', 45, 'C');
Below is the data. Points to be considered :
What does the event mean? What to consider for reviewing?
And here's the query I've tried:
SELECT ds, COUNT(*)/24 AS no_of_job
FROM job_data
WHERE ds BETWEEN '2020-11-01' AND '2020-11-30'
GROUP BY ds;
Check below approach if it is what you are looking for.
select ds,count(job_id) as jobs_per_day, sum(time_spent)/3600 as hours_spent
from job_data
where ds >='2020-11-01' and ds <='2020-11-30'
group by ds ;
Demo MySQL 5.6: https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/26
Demo MySQL 8.0.26: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=83e89a2ad2a7e73b7ca990ac36ae4df0
The difference between the demos as #FaNo_FN pointed out in the comments is: in MySQL 8.0.26version it will provide an error if date 2020-11-31 it is used, because there is no 31 Novembre.
Use and condition instead of between , it performs faster.
You need to sum the time_spent for the day.

Mysql month number to month name conversion

I have month value like "22018" in my column I need it like Feb-2018 in mysql workbench
You need to first extract the month from the date (considering it will have one or two digits), e.g.:
SELECT LPAD(SUBSTRING('22018', 1, LENGTH('22018') - 4), 2, '0');
This will give you 02. Now, you can extract the year with similar logic, e.g.:
SELECT SUBSTRING('22018', LENGTH('22018') - 4 + 1, LENGTH('22018'));
Finally, you can concatenate all these to get a string like 2018-02-01:
SELECT CONCAT(SUBSTRING('22018', LENGTH('22018') - 4 + 1, LENGTH('22018')),
'-',
LPAD(SUBSTRING('22018', 1, LENGTH('22018') - 4), 2, '0'), '-01');
Once this is done, you can use DATE_FORMAT function to get the required output:
SELECT DATE_FORMAT(CONCAT(SUBSTRING('22018', LENGTH('22018') - 4 + 1,
LENGTH('22018')),
'-',
LPAD(SUBSTRING('22018', 1, LENGTH('22018') - 4), 2, '0'), '-01'), '%M-%Y');

Update birthday with full year in MySQL

I have a columns that is for birthday and it's varchar type, I want to change in into date and add full year instead for only 2-digit.
if someone born on 05061985 the MySQL remove first 0 and show as 50685
Change 50685
To ==> 05061985
All users birthday are from 1900 until 1999
Lets do that step by step
We can have strings with len 5 or 6 so we ensure we have a len 6 string left padded with zero
select LPAD('50685', 6, '0');
Now we insert the '19' in the string between the 4th and 5th position
select CONCAT(LEFT(LPAD('50685', 6, '0'), 4), '19', RIGHT(LPAD('50685', 6, '0'), 2));
Now the last step we are going to update all the BIRTHDAY fields in the table FOOBAR
update FOOBAR set BIRTHDAY=CONCAT(LEFT(LPAD(BIRTHDAY, 6, '0'), 4), '19', RIGHT(LPAD(BIRTHDAY, 6, '0'), 2));
Anyway in this case you still have a string field, I suggest to modify the format even more to do a proper date field conversion, something like YYYY-MM-DD
update FOOBAR set BIRTHDAY=LPAD(BIRTHDAY, 6, '0');
update FOOBAR set BIRTHDAY=CONCAT('19' ,
RIGHT(BIRTHDAY, 2),
'-',
SUBSTR(BIRTHDAY, 3, 2),
'-',
LEFT(BIRTHDAY, 2));
alter table FOOBAR modify BIRTHDAY date;

How to format uuid string from binary column in MySQL/MariaDB

In MySQL/MariaDB the most efficient way to store uuid is in a BINARY(16) column. However, sometimes you want to obtain it as a formatted uuid string.
Given the following table structure, how would I obtain all uuids in a default formatted way?
CREATE TABLE foo (uuid BINARY(16));
The following would create the result I was after:
SELECT
LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
))
FROM foo;
MySQL 8 adds two new UUID functions:
UUID_TO_BIN
BIN_TO_UUID - this is the one you're looking for
So:
SELECT BIN_TO_UUID(uuid) FROM foo
In earlier (prior to 8) versions you can create a function in MySQL like the following:
CREATE
FUNCTION uuid_of(uuid BINARY(16))
RETURNS VARCHAR(36)
RETURN LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
));
And then simply use it in your queries:
SELECT
uuid_of(id)
name,
age
FROM users
And it produces:
(c6f5703b-fec2-43fd-8f45-45f06583d450, Some name, 20)
If you are looking for the opposite, i.e., how to convert from string to binary, perhaps to do a join or something, this is covered here : Convert UUID to/from binary in Node
This piece of SQL run on Mysql 5.7 helped lock in the concept for me:
SELECT
LOWER(CONCAT(
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 1, 8), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 9, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 13, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 17, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 21)
))
The output is 43d597d7-2323-325a-90fc-21fa5947b9f3.
string -> binary
So UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', '')) to convert a UUID to binary during an INSERT / UPDATE / JOIN / SELECT whatever, and
binary -> string
LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
))
The correct result is generated by the script below, the other scrips generated a UUID however not the right one.
CONCAT(
substr(hex(Id), 7, 2), substr(hex(Id), 5, 2), substr(hex(Id), 3, 2), substr(hex(Id), 1, 2), '-'
, substr(hex(Id), 11, 2) , substr(hex(Id), 9, 2) , '-'
, substr(hex(Id), 15, 2) , substr(hex(Id), 13, 2) , '-'
, substr(hex(Id), 17, 4) , '-'
, substr(hex(Id), 21, 12)
)
Results running the other scripts generated wrong UUID as per below:
Expected UUID - 2e9660c2-1e51-4b9e-9a86-6db1a2770422
What was generated - c260962e-511e-9e4b-9a86-6db1a2770422
As you can see they are different.
Here's an alternative using concat_ws
Store raw uuid in a variable #x
SELECT #x := hex(uuid)
FROM foo;
Use CONCAT_WS and SUBSTR to parse human readable UUID
SELECT
LOWER(CONCAT_WS('-',
SUBSTR(#x, 1, 8),
SUBSTR(#x, 9, 4),
SUBSTR(#x, 13, 4),
SUBSTR(#x, 17, 4),
SUBSTR(#x, 21)
)) AS uuid;
According to this Jira ticket https://jira.mariadb.org/browse/MDEV-15854 UUID_TO_BIN and BIN_TO_UUID did not make into the Mariadb Server release 10.5. If you are using this version and under of Mariadb Server you will have to use a custom implementation mentioned above.

MySQL, sort integer character by character

Is it possible to sort integers character by character?
So the list [110, 120, 10, 200, 20] would end up like this:
10,
110,
120,
20,
200
If you cast the integer as a varchar or text value, and order by that cast, it should work.
ORDER BY CAST(myField AS CHAR)
SELECT num
FROM your_table
ORDER BY CAST(num as CHAR)