版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kunpeng1987/article/details/76691376
现有如下两张表:
城市表(city)
金额表(money)
需要统计每个城市各月的金额及总额和所有城市每个月的金额和总额。
首先按月份统计各城市的金额
SELECT IFNULL(A.name,'total') as name,SUM(A.pay_money) AS pay_money,A.date_time as date_time FROM
(
SELECT c.name,m.pay_money AS pay_money,DATE_FORMAT( from_unixtime(m.order_time),'%Y%m') as date_time FROM money m INNER JOIN city c ON c.id = m.cid
)AS A GROUP BY date_time, name WITH ROLLUP HAVING date_time is NOT NULL
这里有几个函数介绍一下:
IFNULL(exp1,exp2),如果exp1为null,则返回exp2,否则返回exp1。
IF(exp1,exp2,exp3),如果exp1是TRUE(exp1<>0且exp1<>NULL),那么IF()返回exp2,否则它返回exp3。
with rollup 组内聚合。
结果如下:
然后进行嵌套查询,按照城市进行统计
SELECT IFNULL(date_time,'总计')AS '月份',
SUM(if(name = '深圳',pay_money,0))as '深圳',
SUM(if(name = '广州',pay_money,0))as '广州',
SUM(if(name = '东莞',pay_money,0))as '东莞',
SUM(if(name = '惠州',pay_money,0))as '惠州',
SUM(if(name='total',pay_money,0)) as '总计'
FROM ( SELECT IFNULL(A.name,'total') as name,SUM(A.pay_money) AS pay_money,A.date_time as date_time FROM
(
SELECT c.name,m.pay_money AS pay_money,DATE_FORMAT( from_unixtime(m.order_time),'%Y%m') as date_time FROM money m INNER JOIN city c ON c.id = m.cid
)AS A GROUP BY date_time, name WITH ROLLUP HAVING date_time is NOT NULL
)AS B GROUP BY date_time WITH ROLLUP
目前实现的只是静态的,动态的需要用到存储过程的cursor,也就是游标,cursor是一个可读的标识,用来标识数据取到什么地方了。 可以在存储过程,方法和触发器中创建。cursor用于一行一行的迭代的访问查询返回的结果。它不同与普通的sql 语句,一次将所有的结果返回。这样做有什么好处呢?方便你一行一行的操作你的结果啊!
存储过程代码如下:
begin
declare v_1 varchar(1000) CHARACTER SET utf8 default ' SELECT IFNULL(date_time,\'总计\')AS 月份 ' ;
declare v_2 varchar(1000) CHARACTER SET utf8 default ' FROM ( SELECT IFNULL(A.name,\'total\') as name,SUM(A.pay_money) AS pay_money,A.date_time as date_time FROM
(
SELECT c.name,m.pay_money AS pay_money,DATE_FORMAT( from_unixtime(m.order_time),\'%Y%m\') as date_time FROM money m INNER JOIN city c ON c.id = m.cid
)AS A GROUP BY date_time, name WITH ROLLUP HAVING date_time is NOT NULL
)AS B GROUP BY date_time WITH ROLLUP' ;
-- 定义临时参数
declare v_temp varchar(2000) CHARACTER SET utf8;
-- 定义要遍历的变量
declare v_city varchar(100) CHARACTER SET utf8;
-- 定义结束变量
declare stop int default 0;
-- 定义游标 去查询城市
declare cur cursor for select name from city ;
-- 一个没找到的回调设置
declare continue handler for not found set stop = 1;
-- 游标 遍历 拼接sql字符串
OPEN cur;
FETCH cur INTO v_city;
WHILE stop = 0
DO
if v_temp = '' then
set v_temp = CONCAT(v_1,'sum(if(name =\'',v_city,'\'');
set v_1 = CONCAT(v_temp,',pay_money,0)) as ',v_city);
else
set v_temp = '';
set v_temp = CONCAT(v_1,',','sum(if(name =\'',v_city,'\'','');
set v_1 = CONCAT(v_temp,',pay_money,0)) as ',v_city);
end if;
FETCH cur INTO v_city;
END WHILE;
CLOSE cur;
set @v_result = CONCAT(v_1,', sum(if(name=\'total\',pay_money,0)) as \'总计\'');
set @v_result = CONCAT(@v_result,v_2);
-- 执行sql
prepare stmt from @v_result;
EXECUTE stmt ;
deallocate prepare stmt;
end
下面再新增两个城市,调用存储过程一样可以取出数据。
扫描二维码关注公众号,回复:
2978276 查看本文章