先來一個簡單的summysql
select sum(qty) as total_qty from inventory_product group by product_idsql
這樣就會統計出全部product的qty.數據庫
可是很不幸,咱們的系統裏面竟然有qty爲負值。而我只想統計那些正值的qty,加上if function就能夠了。 SQL爲:博客
select sum(if(qty > 0, qty, 0)) as total_qty from inventory_product group by product_idqt
意思是若是qty > 0, 將qty的值累加到total_qty, 不然將0累加到total_qty.it
如下是sum(if())的例子:io
1 2 3 4 5 select sum( if( qty > 0, qty, 0)) as total_qty , sum( if( qty < 0, 1, 0 )) as negative_qty_count from inventory_product group by product_idtable
上面主要介紹sum (if())的定義,如下是關於數據庫行列轉換的一些方法整理,也是拷貝其餘網友的博客的,作了一些刪減。function
現整理解法以下:class
數據樣本:
create table tx( id int primary key, c1 char(2), c2 char(2), c3 int );
insert into tx values (1 ,'A1','B1',9), (2 ,'A2','B1',7), (3 ,'A3','B1',4), (4 ,'A4','B1',2), (5 ,'A1','B2',2), (6 ,'A2','B2',9), (7 ,'A3','B2',8), (8 ,'A4','B2',5), (9 ,'A1','B3',1), (10 ,'A2','B3',8), (11 ,'A3','B3',8), (12 ,'A4','B3',6), (13 ,'A1','B4',8), (14 ,'A2','B4',2), (15 ,'A3','B4',6), (16 ,'A4','B4',9), (17 ,'A1','B4',3), (18 ,'A2','B4',5), (19 ,'A3','B4',2), (20 ,'A4','B4',5);
mysql> select * from tx; +----+------+------+------+ | id | c1 | c2 | c3 | +----+------+------+------+ | 1 | A1 | B1 | 9 | | 2 | A2 | B1 | 7 | | 3 | A3 | B1 | 4 | | 4 | A4 | B1 | 2 | | 5 | A1 | B2 | 2 | | 6 | A2 | B2 | 9 | | 7 | A3 | B2 | 8 | | 8 | A4 | B2 | 5 | | 9 | A1 | B3 | 1 | | 10 | A2 | B3 | 8 | | 11 | A3 | B3 | 8 | | 12 | A4 | B3 | 6 | | 13 | A1 | B4 | 8 | | 14 | A2 | B4 | 2 | | 15 | A3 | B4 | 6 | | 16 | A4 | B4 | 9 | | 17 | A1 | B4 | 3 | | 18 | A2 | B4 | 5 | | 19 | A3 | B4 | 2 | | 20 | A4 | B4 | 5 | +----+------+------+------+ 20 rows in set (0.00 sec)
mysql>
指望結果
+------+-----+-----+-----+-----+------+ |C1 |B1 |B2 |B3 |B4 |Total | +------+-----+-----+-----+-----+------+ |A1 |9 |2 |1 |11 |23 | |A2 |7 |9 |8 |7 |31 | |A3 |4 |8 |8 |8 |28 | |A4 |2 |5 |6 |14 |27 | |Total |22 |24 |23 |40 |109 | +------+-----+-----+-----+-----+------+
- 利用SUM(IF()) 生成列 + WITH ROLLUP 生成彙總行,並利用 IFNULL將彙總行標題顯示爲 Total
mysql> SELECT -> IFNULL(c1,'total') AS total, -> SUM(IF(c2='B1',c3,0)) AS B1, -> SUM(IF(c2='B2',c3,0)) AS B2, -> SUM(IF(c2='B3',c3,0)) AS B3, -> SUM(IF(c2='B4',c3,0)) AS B4, -> SUM(IF(c2='total',c3,0)) AS total -> FROM ( -> SELECT c1,IFNULL(c2,'total') AS c2,SUM(c3) AS c3 -> FROM tx -> GROUP BY c1,c2 -> WITH ROLLUP -> HAVING c1 IS NOT NULL -> ) AS A -> GROUP BY c1 -> WITH ROLLUP; +-------+------+------+------+------+-------+ | total | B1 | B2 | B3 | B4 | total | +-------+------+------+------+------+-------+ | A1 | 9 | 2 | 1 | 11 | 23 | | A2 | 7 | 9 | 8 | 7 | 31 | | A3 | 4 | 8 | 8 | 8 | 28 | | A4 | 2 | 5 | 6 | 14 | 27 | | total | 22 | 24 | 23 | 40 | 109 | +-------+------+------+------+------+-------+ 5 rows in set, 1 warning (0.00 sec)
-
利用SUM(IF()) 生成列 + UNION 生成彙總行,並利用 IFNULL將彙總行標題顯示爲 Total mysql> select c1, -> sum(if(c2='B1',C3,0)) AS B1, -> sum(if(c2='B2',C3,0)) AS B2, -> sum(if(c2='B3',C3,0)) AS B3, -> sum(if(c2='B4',C3,0)) AS B4,SUM(C3) AS TOTAL -> from tx -> group by C1 -> UNION -> SELECT 'TOTAL',sum(if(c2='B1',C3,0)) AS B1, -> sum(if(c2='B2',C3,0)) AS B2, -> sum(if(c2='B3',C3,0)) AS B3, -> sum(if(c2='B4',C3,0)) AS B4,SUM(C3) FROM TX -> ; +-------+------+------+------+------+-------+ | c1 | B1 | B2 | B3 | B4 | TOTAL | +-------+------+------+------+------+-------+ | A1 | 9 | 2 | 1 | 11 | 23 | | A2 | 7 | 9 | 8 | 7 | 31 | | A3 | 4 | 8 | 8 | 8 | 28 | | A4 | 2 | 5 | 6 | 14 | 27 | | TOTAL | 22 | 24 | 23 | 40 | 109 | +-------+------+------+------+------+-------+ 5 rows in set (0.00 sec)
-
利用SUM(IF()) 生成列,直接生成結果再也不利用子查詢 mysql> select ifnull(c1,'total'), -> sum(if(c2='B1',C3,0)) AS B1, -> sum(if(c2='B2',C3,0)) AS B2, -> sum(if(c2='B3',C3,0)) AS B3, -> sum(if(c2='B4',C3,0)) AS B4,SUM(C3) AS TOTAL -> from tx -> group by C1 with rollup ; +--------------------+------+------+------+------+-------+ | ifnull(c1,'total') | B1 | B2 | B3 | B4 | TOTAL | +--------------------+------+------+------+------+-------+ | A1 | 9 | 2 | 1 | 11 | 23 | | A2 | 7 | 9 | 8 | 7 | 31 | | A3 | 4 | 8 | 8 | 8 | 28 | | A4 | 2 | 5 | 6 | 14 | 27 | | total | 22 | 24 | 23 | 40 | 109 | +--------------------+------+------+------+------+-------+ 5 rows in set (0.00 sec)
-
動態,適用於列不肯定狀況,
mysql> SET @EE=''; mysql> SELECT @EE:=CONCAT(@EE,'SUM(IF(C2='',C2,''',',C3,0)) AS ',C2,',') FROM (SELECT DISTINCT C2 FROM TX) A;
mysql> SET @QQ=CONCAT('SELECT ifnull(c1,'total'),',LEFT(@EE,LENGTH(@EE)-1),' ,SUM(C3) AS TOTAL FROM TX GROUP BY C1 WITH ROLLUP'); Query OK, 0 rows affected (0.00 sec)
mysql> PREPARE stmt2 FROM @QQ; Query OK, 0 rows affected (0.00 sec) Statement prepared
mysql> EXECUTE stmt2; +--------------------+------+------+------+------+-------+ | ifnull(c1,'total') | B1 | B2 | B3 | B4 | TOTAL | +--------------------+------+------+------+------+-------+ | A1 | 9 | 2 | 1 | 11 | 23 | | A2 | 7 | 9 | 8 | 7 | 31 | | A3 | 4 | 8 | 8 | 8 | 28 | | A4 | 2 | 5 | 6 | 14 | 27 | | total | 22 | 24 | 23 | 40 | 109 | +--------------------+------+------+------+------+-------+ 5 rows in set (0.00 sec)
5.使用case,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 SELECT ifnull(c1,'total')`, MAX( CASE WHEN c2= 'B1' THEN C3 END ) AS B1, MAX( CASE WHEN c2= 'B2' THEN C3 END ) AS B2, MAX( CASE WHEN c2= 'B3' THEN C3 END ) AS B3, MAX( CASE WHEN c2= 'B4' THEN C3 END ) AS B4 FROM tx GROUP BY c1
其實數據庫中也能夠用 CASE WHEN / DECODE 代替 IF