设为首页 加入收藏

TOP

[MySQL]行列转换变化各种方法实现总结(行变列报表统计、列变行数据记录统计等)(四)
2015-11-21 01:34:33 来源: 作者: 【 】 浏览:1
Tags:MySQL 行列 转换 变化 各种 方法 实现 总结 报表 统计 数据 记录
all' , cname AS "姓名", MAX(CASE cource WHEN "语文" THEN score ELSE 0 END) AS "语文", MAX(CASE cource WHEN "数学" THEN score ELSE 0 END) AS "数学", MAX(CASE cource WHEN "物理" THEN score ELSE 0 END) AS "物理", SUM(score) AS "总成绩", ROUND(AVG(score) ,2) AS "平均成绩" FROM tb GROUP BY `cname` )tb2 GROUP BY tb2.all?

执行结果正确,如下所示:

+--------------------+--------+--------+--------+-----------+--------------+

| 姓名 | 语文 | 数学 | 物理 | 总成绩 | 平均成绩 |

+--------------------+--------+--------+--------+-----------+--------------+

| 张三 | 74.00 | 83.00 | 93.00 | 250.00 | 83.33 |

| 李四 | 74.00 | 84.00 | 94.00 | 252.00 | 84.00 |

| 总成绩平均数 | 74.00 | 83.50 | 93.50 | 251.00 | 83.67 |

+--------------------+--------+--------+--------+-----------+--------------+

4,利用 WITH rollup结果不符合

SQL代码如下:
  SELECT IFNULL(cname,'总平均数') AS "姓名",
	MAX(CASE cource WHEN "语文" THEN score ELSE 0 END) AS "语文", 
	MAX(CASE cource WHEN "数学" THEN score ELSE 0 END) AS "数学", 
	MAX(CASE cource WHEN "物理" THEN score ELSE 0 END) AS "物理", 
	ROUND(AVG(score),2) AS "总成绩",
	ROUND(AVG(avg_score),2) AS "平均成绩" 
    FROM(
	SELECT   
		cname ,
		IFNULL(cource,'total') cource,
		SUM(score) AS score,
		ROUND(AVG(score) ,2) AS avg_score
	FROM tb 
	GROUP BY `cname`,cource WITH ROLLUP HAVING cname IS NOT NULL
	)tb2 
	GROUP BY  tb2.cname WITH ROLLUP;
mysql>     SELECT IFNULL(cname,'总平均数') AS "姓名",
    -> MAX(CASE cource WHEN "语文" THEN score ELSE 0 END) AS "语文", 
    -> MAX(CASE cource WHEN "数学" THEN score ELSE 0 END) AS "数学", 
    -> MAX(CASE cource WHEN "物理" THEN score ELSE 0 END) AS "物理", 
    -> ROUND(AVG(score),2) AS "总成绩",
    -> ROUND(AVG(avg_score),2) AS "平均成绩" 
    ->     FROM(
    -> SELECT   
    -> 
Display ALL 793 possibilities? (Y OR n) 
    -> cname ,
    -> 
Display ALL 793 possibilities? (Y OR n) 
    -> IFNULL(cource,'total') cource,
    -> 
Display ALL 793 possibilities? (Y OR n) 
    -> SUM(score) AS score,
    -> 
Display ALL 793 possibilities? (Y OR n) 
    -> ROUND(AVG(score) ,2) AS avg_score
    -> FROM tb 
    -> GROUP BY `cname`,cource WITH ROLLUP HAVING cname IS NOT NULL
    -> )tb2 
    -> GROUP BY  tb2.cname WITH ROLLUP;
+--------------+--------+--------+--------+-----------+--------------+
| 姓名         | 语文   | 数学   | 物理   | 总成绩    | 平均成绩     |
+--------------+--------+--------+--------+-----------+--------------+
| 张三         |     74 |     83 |     93 |    125.00 |        83.33 |
| 李四         |     74 |     84 |     94 |    126.00 |        84.00 |
| 总平均数     |     74 |     84 |     94 |    125.50 |        83.67 |
+--------------+--------+--------+--------+-----------+--------------+
3 ROWS IN SET, 1 warning (0.00 sec)
mysql> 

总结: WITH rollup中对求列的总数是OK的,但是求列的平均数有偏差,这里场景使用不是恰当。

5,使用动态SQL来实现

SQL代码块如下:

/*仅仅班级成员部分*/
SET @a=''; 
SELECT @a:=CONCAT(@a,'SUM(IF(cource=\'',cource,'\'',',score,0)) AS ',cource,',') FROM (SELECT DISTINCT cource FROM tb) A;
SET @a=CONCAT(@a,"ROUND(AVG(score) ,2) AS \"平均成绩\"");
SET @b=CONCAT('SELECT IFNULL(cname,\'总成绩\'),',LEFT(@a,LENGTH(@a)-1),' ,SUM(score) AS \"总成绩\" FROM tb GROUP BY cname ');

/*班级成员总计部分**/
SET @a2="";
SET @b2=CONCAT('SELECT "all",IFNULL(cname,\'总成绩\'),',LEFT(@a,LENGTH(@a)-1),' ,SUM(score) AS \"总成绩\" FROM tb GROUP BY cname ');
SELECT @a2:=CONCAT(@a2,'ROUND(AVG(`',cource,'`),2),') FROM (SELECT DISTINCT cource FROM tb) A;
SET @a2=CONCAT(@a2," ROUND(AVG(`平均成绩`),2),ROUND(AVG(`总成绩`),2) ");
SET @c=CONCAT("SELECT \"班级平均数\",",LEFT(@a2,LENGTH(@a)-1)," FROM(",@b2,")tb2 GROUP BY tb2.all;");
SET @d=CONCAT(@b," UNION ALL ",@c);

PREPARE stmt1 FROM @d;
EXECUTE stmt1;?

查看执行结果如下,已经达到效

首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇为什么你应该永远不要再使用Mongo.. 下一篇最小公约数

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: