iT邦幫忙

DAY 12
5

MySQL那些事兒系列 第 12

MySQL GROUP BY ROLLUP 的應用

GROUP BY 的應用很廣泛,再搭配ROLLUP使用就更強大了.
先建立測試用的Table,為使討論的重點在ROLLUP上,故
測試Table是簡化的,實務應用上可能會是JOIN數個Table
的情況.

CREATE TABLE ithelp1012(
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name CHAR(10) NOT NULL,
type CHAR(4) NOT NULL,
qty TINYINT UNSIGNED NOT NULL);


INSERT INTO ithelp1012(name, type, qty) VALUES
('小雨', 'AV', 20),
('泰大', 'AV', 30),
('太陽大', 'AV', 40),
('榮哥', 'AV', 50),
('小雨', 'BOOK', 10),
('泰大', 'BOOK', 50),
('太陽大', 'BOOK', 60),
('榮哥', 'BOOK', 30);

利用 GROUP BY 來作總計,例如得到測試資料中,所有人擁有的書籍數目,相信大家都很熟悉了,在此就不浪費篇幅與大家寶貴的時間了.
直接來看 ROLLUP 的運用.

SELECT name
     , type
     , SUM(qty) AS sqty
  FROM ithelp1012
 GROUP BY name, type
  WITH ROLLUP;

+-----------+------+------+
| name      | type | sqty |
+-----------+------+------+
| 太陽大    | AV   |   40 |
| 太陽大    | BOOK |   60 |
| 太陽大    | NULL |  100 |
| 小雨      | AV   |   20 |
| 小雨      | BOOK |   10 |
| 小雨      | NULL |   30 |
| 榮哥      | AV   |   50 |
| 榮哥      | BOOK |   30 |
| 榮哥      | NULL |   80 |
| 泰大      | AV   |   30 |
| 泰大      | BOOK |   50 |
| 泰大      | NULL |   80 |
| NULL      | NULL |  290 |
+-----------+------+------+
13 rows in set (0.00 sec)

可以很輕易的了解到 太陽大擁有的媒體(AV,BOOK)總數為100.
大家全部的媒體(AV,BOOK)總數為290.
個別的也都顯示出來了.

但是MySQL在小計與總計的部份都用NULL來顯示,
對查看資料時的感覺與可讀性都不夠好.
可以用以下方法改良

SELECT IFNULL(name, '總計:') AS '姓名'
     , IFNULL(type, '小計:') AS '媒體種類'
     , SUM(qty) AS 'sqty'
  FROM ithelp1012
 GROUP BY name, type
  WITH ROLLUP;

+-----------+--------------+------+
| 姓名      | 媒體種類     | sqty |
+-----------+--------------+------+
| 太陽大    | AV           |   40 |
| 太陽大    | BOOK         |   60 |
| 太陽大    | 小計:        |  100 |
| 小雨      | AV           |   20 |
| 小雨      | BOOK         |   10 |
| 小雨      | 小計:        |   30 |
| 榮哥      | AV           |   50 |
| 榮哥      | BOOK         |   30 |
| 榮哥      | 小計:        |   80 |
| 泰大      | AV           |   30 |
| 泰大      | BOOK         |   50 |
| 泰大      | 小計:        |   80 |
| 總計:     | 小計:        |  290 |
+-----------+--------------+------+
13 rows in set (0.00 sec)

看起來好一些了.但還不夠好,最後總計那裡還是看起來不順眼.
再利用一些判斷的函數,來作改良.

SELECT IFNULL(name, '總計:') AS '姓名'
     , IF(IFNULL(name, 1) 
         ,''
         ,IFNULL(type, '小計')
         ) AS '媒體種類'
     , SUM(qty) AS 'sqty'
  FROM ithelp1012
 GROUP BY name, type
  WITH ROLLUP;

+-----------+--------------+------+
| 姓名      | 媒體種類     | sqty |
+-----------+--------------+------+
| 太陽大    | AV           |   40 |
| 太陽大    | BOOK         |   60 |
| 太陽大    | 小計         |  100 |
| 小雨      | AV           |   20 |
| 小雨      | BOOK         |   10 |
| 小雨      | 小計         |   30 |
| 榮哥      | AV           |   50 |
| 榮哥      | BOOK         |   30 |
| 榮哥      | 小計         |   80 |
| 泰大      | AV           |   30 |
| 泰大      | BOOK         |   50 |
| 泰大      | 小計         |   80 |
| 總計:     |              |  290 |
+-----------+--------------+------+
13 rows in set (0.00 sec)

這樣就看起來可讀性更好了.


上一篇
MySQL Query Profing 的再進一步改進
下一篇
補助表的運用
系列文
MySQL那些事兒30

1 則留言

0
奈特
iT邦新手 4 級 ‧ 2019-04-19 09:43:11

請問這段查詢能在加入 name 的總計嗎? (不重複計算)

能再詳細說一下,你說的 name 的總計, 是怎樣計算?
能舉例嗎?

我要留言

立即登入留言