Mysql一维表转二维表,动态的行转列

这篇具有很好参考价值的文章主要介绍了Mysql一维表转二维表,动态的行转列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

想利用Grafana做数据展示,将一维的长表优化成二维数据表格展示。

将一维表转换为二维表,也就是将行转换为列,可以使用MySQL的PIVOT语句来完成。

PIVOT是一种在关系型数据库中将行转换为列的技术。在MySQL中,可以使用PIVOT语句将普通的查询结果转换为一个带有动态列的表格。

PIVOT语句通过将行的值转换为列的值来重新排列数据。在MySQL中,PIVOT语句通常使用聚合函数(如SUM、MAX、MIN等)来对数据进行汇总,以便在转换后的表格中每个单元格只有一个值。

假设条件

假设我们有一个名为“orders”的表,其中存储了订单的信息,包括订单号、商品名称和商品数量:

CREATE TABLE orders (
    order_id INT,
    product_name VARCHAR(50),
    quantity INT
);

现在,我们想将这个一维表转换为二维表,其中每列都代表一个商品名称,每行都代表一个订单,数量为该订单中该商品的数量。

实际两种处理情况

若是要转换成的二维表的表头是已知固定的,则为静态转换
若是要转换成的二维表的表头是不确定的,根据数据动态增加,则为动态转换

静态转换
SELECT order_id,
       MAX(CASE WHEN product_name = 'Product A' THEN quantity END) AS 'Product A',
       MAX(CASE WHEN product_name = 'Product B' THEN quantity END) AS 'Product B',
       MAX(CASE WHEN product_name = 'Product C' THEN quantity END) AS 'Product C'
FROM orders
GROUP BY order_id;

或者使用IF判断

SELECT order_id,
	Sum(if(product_name = 'Product A',quantity,0)) AS 'Product A',
	Sum(if(product_name = 'Product B',quantity,0)) AS 'Product B',
	Sum(if(product_name = 'Product C',quantity,0)) AS 'Product C',
FROM orders
GROUP BY order_id;

聚合函数(SUM、MAX、MIN)可以根据需要替换

动态转换

使用动态SQL生成PIVOT语句的具体实现方法可以根据您的具体情况而定,常用以下两种方式:

  • 使用存储过程:可以编写一个存储过程,该存储过程接受列名称作为输入参数,并使用动态SQL生成PIVOT语句。存储过程可以将查询结果作为参数返回,并将结果集转换为带有动态列的表格。这种方法的好处是可以将查询逻辑封装在存储过程中,使代码更加模块化和可重用。

  • 使用预处理语句:可以编写一个包含动态列名称的字符串,并在MySQL中使用预处理语句来执行动态SQL。这种方法的好处是可以将查询逻辑与数据分离,并且可以减少SQL注入的风险。

存储过程方式

  1. 创建一个存储过程,该存储过程接受列名称作为输入参数,并使用动态SQL生成PIVOT语句。以下是一个示例:
DELIMITER $$
CREATE PROCEDURE pivot_sales(IN col_name VARCHAR(50))
BEGIN
    SET @cols = (SELECT GROUP_CONCAT(DISTINCT CONCAT('MAX(CASE WHEN ', col_name, ' = ''', 
                    REPLACE(val, '''', ''''''), ''' THEN amount END) AS ''', 
                    REPLACE(val, '''', ''''''))) 
                FROM sales
                CROSS JOIN (SELECT DISTINCT val FROM sales WHERE col_name = 'region') r;
    SET @query = CONCAT('SELECT date, ', @cols, ' FROM sales GROUP BY date');
    PREPARE stmt FROM @query;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;

说明:DEALLOCATE PREPARE语句用于释放由PREPARE语句占用的资源。在MySQL中,PREPARE语句用于准备动态SQL,并将其存储在MySQL服务器的缓存中。当不再需要动态SQL时,可以使用DEALLOCATE PREPARE语句来释放缓存中的语句,以释放资源并减少内存使用。

说明:DELIMITER是MySQL中的一个命令,它用于更改SQL语句的结束符号(通常为分号)。在默认情况下,MySQL使用分号作为SQL语句的结束符号。但是,当在存储过程或函数中使用多条SQL语句时,分号可能会被解释为SQL语句的结束符号,从而导致语法错误。

为了避免这个问题,可以使用DELIMITER命令更改SQL语句的结束符号,例如将结束符号更改为$$。这样,使用分号作为SQL语句的内部结束符号不会与外部SQL语句的结束符号冲突。

在使用DELIMITER命令时,应该首先使用DELIMITER命令设置新的结束符号,然后编写SQL语句,并使用新的结束符号结束SQL语句。最后,应该使用DELIMITER命令将结束符号更改回原始值。

  1. 调用存储过程并将列名称作为参数传递。以下是一个示例:
CALL pivot_sales('region');

存储过程中的动态SQL可能会导致SQL注入的风险,因此应该谨慎使用,并确保输入的列名称是可信的。

预处理语句方式(常用)

SET @cols = (SELECT 
				GROUP_CONCAT(DISTINCT 
					CONCAT('MAX(CASE WHEN region = ''', region, ''' THEN sales END) AS ', region)
				) 
			FROM sales);
			
SET @query = CONCAT('SELECT date, ', @cols, ' FROM sales GROUP BY date');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

在这个示例中,我们使用了MySQL的GROUP_CONCAT函数来动态生成列名称,然后使用CONCAT函数将列名称与PIVOT语句组合在一起。最后,我们使用PREPARE语句来准备动态SQL并使用EXECUTE语句来执行动态SQL。文章来源地址https://www.toymoban.com/news/detail-607086.html

到了这里,关于Mysql一维表转二维表,动态的行转列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL中的经典面试题——行转列(列转行)

    目录 1、简介:   1. 行转列(Pivot): 2. 列转行(Unpivot): 2、行转列,列转行的思想 3、实现 3.1、实现行转列 3.2、总结(行转列)实现的两种方法   3.3、实现(列转行)  3.4、总结 (列转行)         在MySQL中,行转列(Pivot)和列转行(Unpivot)是用于改变数据表格

    2024年02月03日
    浏览(45)
  • Mysql 行转列,把逗号分隔的字段拆分成多行

    源数据 变更后的数据 第一种 先执行下面的SQL,看不看能不能执行,如果有结果,代表数据库版本是可以的,可以看下面和自己表关联的SQL,如果不行用第二种。 示例SQL 和业务结合在一起使用 其核心在于 mysql.help_topic ,但是版本太低的数据库版本不支持,如果不支持,可以

    2024年02月02日
    浏览(42)
  • 搞定mysql的 行转列(7种方法) 和 列转行

    一、行转列 1、使用case…when…then  2、使用SUM(IF()) 生成列 3、使用SUM(IF()) 生成列 + WITH ROLLUP 生成汇总行 4、使用SUM(IF()) 生成列,直接生成汇总结果,不再利用子查询 5、使用SUM(IF()) 生成列 + UNION 生成汇总行,并利用 IFNULL将汇总行标题显示为 Total 6、动态查询列值不确定的情况

    2024年03月12日
    浏览(54)
  • MySQL中的面试题——行转列(列转行)手把手详解思想

    目录 1、什么是行转列,列转行 ? 1.1、概念: 1.2、行转列和列转行的思想 1.2.1、行转列的思想? 1.2.2、列转行的思想? 3、实操讲解 3.1、实现行转列  3.2、总结:行转列实现的两种方法    3.3、实现列转行  3.4、总结 :列转行 4、动手练习         在MySQL中,行转列(

    2024年02月03日
    浏览(61)
  • 【业务功能篇20】Springboot java逻辑实现动态行转列需求

    在此前,我也写过一个行转列的文章,是用存储过程sql处理的一个动态的逻辑 Mysql 存储过程Mybatis框架call调用 实现动态行转列 那么后面我们同样又接收了业务的一个新需求,针对的是不同的业务数据,做的同样的一个展示数据报表,同样还是产品归属信息表头,拼接查询年

    2024年02月09日
    浏览(46)
  • 动态规划—— 01背包问题(一维,二维)

    0-1背包问题是一个经典问题,特别是在算法和动态规划领域。问题是关于一个小偷,他有一个可以携带最大重量的背包,并且他有一组物品,其中每个物品都有自己的价值和重量。小偷希望在不超过背包所能承载的最大重量的情况下,最大化他从这些物品中获得的总价值。问

    2024年02月19日
    浏览(44)
  • sql 行转列

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 实现行转列的两种方式,case when 与piovt 函数的使用例子与比对 示例:如需要将左边的表格转换成右边的表格 首先,根据资产属性先将数据分成四列 代码如下:` 结果如下: I 这样看起来比较乱,需要根

    2024年02月09日
    浏览(41)
  • greenplum行转列

    项目中需要将150w的数据转为1500列的大宽表数据。 最开始尝试了网上提供的两种方法: 实际业务中10行*1500列数据查询并插入需要25秒左右(测试服务器性能比较差) case when的问题是每个case when的语句都会把分组后的数据判断一下,时间复杂度为O²(O为行转列后的列数),非

    2024年02月03日
    浏览(41)
  • SqlServer行转列方法

    数据库建表 1 使用聚合函数巧妙解决,可以用max、sum等 2 使用pivot函数 3.行转列,多列,参考

    2024年02月15日
    浏览(69)
  • PostgreSQL如何行转列

    PostgreSQL如何行转列 方法一: group by + sum + case when 方法二: 用postgresql的crosstab交叉函数 方法三: group by + string_agg + split_part(分组,行转列,字符切割) group by + string_agg

    2024年02月11日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包