MySQL将字节转换为千字节、兆字节、吉字节

16

我有一张记录各种文件大小的日志表,以字节为单位存储。我希望能够查询数据库并返回已转换为MB、GB等的最小可能浮点数。目前我可以返回MB中的值,但是如何继续分割到最小值并附加单位呢?

SELECT CONCAT( ROUND( SUM( data_transferred ) /1048576, 2 ) ,  ' MB' ) 
FROM  `logs`

任何帮助将不胜感激。

更新:

根据voodoo417提供的链接,我更新了我的查询语句如下,它将输出最相关的文件大小到两个小数位,并附加单位(1000字节,1千字节,500兆字节,2千兆字节,等等):

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

1
你能提供一些你想要的结果的例子吗? - Gordon Linoff
如voodoo417所链接的,但我想在不定义用户函数的情况下执行此操作。http://myitforum.com/cs2/blogs/jnelson/archive/2008/01/11/111351.aspx - user2985091
5个回答

21

我知道这是一个老问题,但最近我也在寻找同样的东西,发现MySQL 5.7专门为此新增了format_bytes函数:

mysql> SELECT format_bytes(512), format_bytes(18446644073709551615);
+-------------------+------------------------------------+
| format_bytes(512) | format_bytes(18446644073709551615) |
+-------------------+------------------------------------+
| 512 bytes         | 16383.91 PiB                       |
+-------------------+------------------------------------+

2
SELECT VERSION(): 5.7.18-0ubuntu0.16.04.1 Kernel error: Error( 1305 ) 42000: "FUNCTION format_bytes does not exist". 是的,我看到了文档 :) - PawelN
3
https://github.com/mysql/mysql-sys/blob/master/functions/format_bytes.sql - nono
1
需要使用sys模式吗?看起来是这样的。 - Andrea Bergonzo
5
是的,确实需要使用sys.format_bytes - Tim
仅适用于MariaDB 10.6:https://mariadb.com/kb/en/sys-schema/ - Ortomala Lokni

6
我有一个更优雅的解决方案(也使用了用户定义函数):
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

更新:

更好的是,这可以在程序之外使用:

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'));

5

当文件大小为0时,Renaat的代码会出现故障(显然,您无法从零开始进行LOG操作)。因此,@log被填充为null,CONCAT也会产生null。 正确的修复方法是:

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'));

0

关于使用format_bytes的最佳答案,尽管是在2016年回答的,但可悲的是在MariaDB中仍然找不到。

我从这里改编了查询,以便制作一个我可以使用的函数。

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                           |
+-------------------+------------------------------------+

有些东西可以调整一下,更接近于MySQL的format_bytes,但这不是我想要的。


0

select concat(round(data*1048576/1073741824,2),' GB')

例如:1024 = 1GB select concat(round(1024*1048576/1073741824,2),' GB') 1GB


2
请格式化您的答案,并详细说明如何回答问题。 - Farside

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接