Date time difference in mysql shows incorrect result - mysql

select CONCAT(
Lpad(
FLOOR(HOUR(TIMEDIFF('2015-06-25 12:10', '2011-06-21 10:10')) / 24),
4,0),':',
Lpad(
MOD(HOUR(TIMEDIFF('2014-06-25 12:10', '2015-06-21 10:10')), 24),
4,0),':',
Lpad(
MINUTE(TIMEDIFF('2014-06-25 12:10', '2015-06-21 10:15')),
4,0), '')
The above MySQL select statement gives
incorrect report.Required format of date = days:hours:minutes

The functions you are using are limited by the TIME type that may range from '-838:59:59' to '838:59:59'. you should use TIMESTAMPDIFF which return integers.
select
TIMESTAMPDIFF(DAY,'2011-06-21 10:10','2015-06-25 12:10') as c_days,
TIMESTAMPDIFF(HOUR,'2014-06-25 12:10', '2015-06-21 10:10') as c_hrs,
TIMESTAMPDIFF(MINUTE,'2014-06-25 12:10', '2015-06-21 10:15') as c_mnt;
but this doesn't make much sense you've probably have some typos in your formula, the code bellow is probably what you're looking for.
set #a_mnt := TIMESTAMPDIFF(MINUTE,'2014-06-25 12:10', '2015-06-21 10:10');
select
concat(
lpad(floor(#a_mnt := #a_mnt / 1440 ), 4, 0), ':',
lpad(floor(#a_mnt := ((#a_mnt - floor(#a_mnt)) * 24)), 4, 0), ':',
lpad(floor((#a_mnt - floor(#a_mnt)) * 60 ), 4, 0)) as result;

Related

MySql function: Hexadecimal conversation to Float

I have a bit of a challenge in converting a hexadecimal string into a float.
Here is an example:
Hex:
3F62 0C3C
Binary: 00111111011000100000110000111100
Conversion result (float big endian):
0.8829992
Can this conversion be achieved with MySql functions and, if possible, how?
Thank you for your help.
So, I assume you have your hexadecimal string in some sort of TEXT type:
SELECT #hexstring := '3F62 0C3C'
The first thing you need to do is to convert it to a decimal. You can do this using the CONV function. For that, first remove the whitespace from the string with the REPLACE function. Depending on the parameters of the CONV function, you can e.g. get a binary or a decimal representation:
SELECT #binvalue := CONV(REPLACE(#hexstring, ' ', ''), 16, 2) -- 111111011000100000110000111100
SELECT #decvalue := CONV(REPLACE(#hexstring, ' ', ''), 16, 10) -- 1063390268
From the decimal representation, you can calculate your float (based on this SO answer):
SELECT SIGN(#decvalue) * (1.0 + (#decvalue & 0x007FFFFF) * POWER(2.0, -23))
* POWER(2.0, (#decvalue & 0x7f800000) / 0x00800000 - 127)
Result:
0.8829991817474365
Or all in one:
SELECT SIGN(CONV(REPLACE(#hexstring, ' ', ''), 16, 10))
* (1.0 + (CONV(REPLACE(#hexstring, ' ', ''), 16, 10) & 0x007FFFFF)
* POWER(2.0, -23))
* POWER(2.0, (CONV(REPLACE(#hexstring, ' ', ''), 16, 10) & 0x7f800000) / 0x00800000 - 127)
Test all of it together in this db<>fiddle.

How to auto increment a string with sql query

I am stuck at a point where i have to increment a string, and my strings are of type C001,SC001,B001
in my data base they are defined like
what i am trying to do do is write a query which check the previous highest code present into my db and the incriment it to +1
for example C001 -> C002,C009->C010,C099`->C100 and so on
Similarly for SC001->SC002,SC009->SC010,SC099->SC100 and so on
Similarly fro B001 -> B002,B009->B010,B099`->B100 and so on
I have a query which my friend has suggested me to use but that query only incriminating AAAA->AAAA01 , AAAA09->AAAA10
query is
SELECT id AS PrevID, CONCAT(
SUBSTRING(id, 1, 4),
IF(CAST(SUBSTRING(id, 5) AS UNSIGNED) <= 9, '0', ''),
CAST(SUBSTRING(id, 5) AS UNSIGNED) + 1
) AS NextID
FROM (
-- since you allow strings such as AAAA20 and AAAA100 you can no longer use MAX
SELECT id
FROM t
ORDER BY SUBSTRING(id, 1, 4) DESC, CAST(SUBSTRING(id, 5) AS UNSIGNED) DESC
LIMIT 1
) x
when i am replacing ID with CategoryCode it is giving me PrevID-C004 NextID-C00401 which is not my requirement i want PrevID-C004 and NextID->C005
NOTE i am using my sqlServer 5.1
Just try this one ,
SELECT
CategoryCode,CAST(CONCAT(LPAD(CategoryCode,1,0),LPAD(MAX(RIGHT(CategoryCode,
3)) + 1, 3, 0) ) AS CHAR),
FROM test
SELECT
SubCategoryCode,CAST(CONCAT(LPAD(SubCategoryCode,2,0),
LPAD(MAX(RIGHT(CategoryCode, 3)) + 1, 3, 0) ) AS CHAR),
FROM test
SELECT
BrandCode,CAST(CONCAT(LPAD(BrandCode,1,0), LPAD(MAX(RIGHT(BrandCode, 3)) +
1, 3, 0)) AS CHAR) FROM test

MySQL Convert Bytes to Kilobytes, Megabytes, Gigabytes

I have a logs table that stores various file sizes in bytes. I want to be able to query the database and return the smallest possible float which has been converted to MB GB etc. At present I can return the value in MB but how do I continue to divide further to smallest value and append the unit?
SELECT CONCAT( ROUND( SUM( data_transferred ) /1048576, 2 ) , ' MB' )
FROM `logs`
Any help would be appreciated.
UPDATE:
Based on the link voodoo417 provided I updated my query to the following, which will output the most relevant file size to two decimal places and append the unit (1000 Bytes, 1 KB, 500 MB, 2 GB, etc):
SET #bytes := (SELECT SUM(data_transferred) FROM wp_ddownload_statistics);
SELECT
CASE
WHEN ABS(#bytes) < 1024 THEN CONCAT( ROUND( #bytes, 2 ), ' Bytes')
WHEN ABS(#bytes) < 1048576 THEN CONCAT( ROUND( (#bytes/1024), 2 ), ' KB')
WHEN ABS(#bytes) < 1073741824 THEN CONCAT( ROUND( (#bytes/1048576), 2 ), ' MB')
WHEN ABS(#bytes) < 1099511627776 THEN CONCAT( ROUND( (#bytes/1073741824), 2 ), ' GB' )
WHEN ABS(#bytes) < 1125899906842624 THEN CONCAT( ROUND( (#bytes/1099511627776), 2 ), ' TB')
WHEN ABS(#bytes) < 1152921504606846976 THEN CONCAT( ROUND( (#bytes/1125899906842624), 2 ), ' PB' )
WHEN ABS(#bytes) < 1180591620717411303424 THEN CONCAT( ROUND( (#bytes/1152921504606846976) ,2), ' EB' )
WHEN ABS(#bytes) < 1208925819614629174706176 THEN CONCAT( ROUND( (#bytes/1180591620717411303424), 2), ' ZB' )
WHEN ABS(#bytes) < 1237940039285380274899124224 THEN CONCAT( ROUND( (#bytes/1208925819614629174706176), 2), ' YB' )
WHEN ABS(#bytes) < 1267650600228229401496703205376 THEN CONCAT( ROUND( (#bytes/1237940039285380274899124224), 2), ' BB' )
END
I know this is an old question, but I was looking for the same thing recently, and found out that MySQL 5.7 added format_bytes function exactly for this purpose:
mysql> SELECT format_bytes(512), format_bytes(18446644073709551615);
+-------------------+------------------------------------+
| format_bytes(512) | format_bytes(18446644073709551615) |
+-------------------+------------------------------------+
| 512 bytes | 16383.91 PiB |
+-------------------+------------------------------------+
I have a more elegant solution (also using a user defined function):
CREATE FUNCTION `format_filesize`(filesize FLOAT) RETURNS varchar(20) CHARSET utf8
BEGIN
DECLARE n INT DEFAULT 1;
LOOP
IF filesize < 1024 THEN
RETURN concat(round(filesize, 2), ' ', elt(n, 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB', 'BB'));
END IF;
SET filesize = filesize / 1024;
SET n = n + 1;
END LOOP;
END
UPDATE:
Even better, and can be used outside procedures:
SET #filesize = 536870912;
SET #log = IFNULL(TRUNCATE(LOG(1024, #filesize), 0),0);
SELECT CONCAT(ROUND(#filesize / POW(1024, #log), 2), ' ',
ELT(#log + 1, 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB', 'BB'));
Renaat's code is failing when filesize is 0 (obviously you can't do LOG from zero). Therefore #log is filled with null and CONCAT produce null as well.
Correct fix is:
SET #filesize = 536870912;
SET #log = IFNULL(TRUNCATE(LOG(1024, #filesize), 0),0);
SELECT CONCAT(ROUND(#filesize / POW(1024, #log), 2), ' ',
ELT(#log + 1, 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB', 'BB'));
select concat(round(data*1048576/1073741824,2),' GB')
for example: 1024 = 1gb
select concat(round(1024*1048576/1073741824,2),' GB')
1gb
The top answer about using format_bytes, despite being answered in 2016, is sadly still not found in MariaDB.
I adapted the query from here to make a function I could use.
FUNCTION `format_bytes`(val float) RETURNS varchar(20) CHARSET latin1
BEGIN
DECLARE pw smallint;
IF val < 1024 THEN
return CONCAT(val, ' B');
END IF;
SET pw = LEAST(7, FLOOR(LOG(val) / LOG(1024)));
RETURN CONCAT(ROUND(val / POW(1024, pw), 2), ' ', SUBSTR('KMGTPEZY', pw, 1), 'B');
END
>>> SELECT format_bytes(512), format_bytes(18446644073709551615);
+-------------------+------------------------------------+
| format_bytes(512) | format_bytes(18446644073709551615) |
+-------------------+------------------------------------+
| 512 B | 16.00 EB |
+-------------------+------------------------------------+
A few things could be tweaked to more closely mimic the MySQL format_bytes, but it's not what I was aiming for.

How to pass from seconds to time

How can I pass from seconds to time on mysql?
the date format of out is hh:mm:ss.ms
Sorry. I need for example 0.98 sec -> 00:00:00.980; With sec_to_tiem return 00:00:01.
thanks.
I have implemeted of this way:
select concat(if(floor(seconds/(60 * 60)) = 0,'00',lpad(floor(seconds/(60 * 60)),2,'0')),
':',
if(floor(seconds/60) = 0,'00',lpad(floor(seconds / 60),2,'0')),
':',
seconds % 60)
but it have to exist other way more efficient
other way:
CONCAT(lpad(floor(seconds / 3600), 2, '0'), ':',
lpad(floor(seconds / 60), 2, '0'), ':',
lpad(floor(seconds % 60), 2, '0'), '.',
lpad(SUBSTRING_INDEX((seconds * 1000) % 1000, '.', 1), 3, '0'))
SELECT MAKETIME (<yourseconds>/(60*24), <yourseconds>/60, <yourseconds>%60)
or with format
SELECT TIME_FORMAT( MAKETIME( <yourseconds>/ ( 60 *24 ) , <yourseconds>/60, <yourseconds>%60 ) , '%T.%f' )

How can I speed up my MySQL UUID v4 stored function?

I'm attempting to write a MySQL stored function to generate v4 UUIDs as described in RFC 4122's section 4.4 ( http://www.ietf.org/rfc/rfc4122.txt ). My initial naive effort after a few tweaks is the following:
CREATE FUNCTION UUID_V4()
RETURNS BINARY(16)
READS SQL DATA
BEGIN
SET #uuid = CONCAT(
LPAD( HEX( FLOOR( RAND() * 4294967296 ) ), 8, '0' ),
LPAD( HEX( FLOOR( RAND() * 4294967296 ) ), 8, '0' ),
LPAD( HEX( FLOOR( RAND() * 4294967296 ) ), 8, '0' ),
LPAD( HEX( FLOOR( RAND() * 4294967296 ) ), 8, '0' )
);
SET #uuid = CONCAT(
SUBSTR( #uuid FROM 1 FOR 12 ),
'4',
SUBSTR( #uuid FROM 14 FOR 3 ),
SUBSTR( 'ab89' FROM FLOOR( 1 + RAND() * 4 ) FOR 1 ),
SUBSTR( #uuid FROM 18 )
);
RETURN UNHEX(#uuid);
END
The above function is quite slow: almost 100 times slower than the built-in UUID(), according to MySQL's BENCHMARK() feature. Short of writing a UDF using MySQL's C API, are there any improvements I can make here to, say, shave off an order of magnitude from its runtime?
If there is an already existing, well-regarded UUID UDF or stored procedure, I'd be happy to hear about that, too.
I didn't test this for correctness or for performance. It is just the idea of doing one only concatenation in instead of two.
create function uuid_v4()
returns binary(16)
begin
set #h1 = lpad(hex(floor(rand() * 4294967296)), 8, '0');
set #h2 = lpad(hex(floor(rand() * 4294967296)), 8, '0');
set #h3 = lpad(hex(floor(rand() * 4294967296)), 8, '0');
set #h4 = lpad(hex(floor(rand() * 4294967296)), 8, '0');
set #uuid = concat(
#h1,
substr(#h2 from 1 for 4),
'4',
substr(#h2 from 6),
substr('ab89' from floor(1 + rand() * 4) for 1 ),
substr(#h3 from 2),
#h4
);
return unhex(#uuid);
end
;
Also why do you use READS SQL DATA in your function?