假设用户需要对 N 个唯独进行聚合查询操作,普通的 group by 语句需要 N 个查询和 N 次 group by 操作。
而 rollup 的有点是一次可以去的 N 次 group by 的结果,这样可以提高查询效率,同时大大减少网络的传输流量。
(注,此表的表结构和数据与格式化聚合表 formatting 一致)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
CREATE TABLE rollup( orderid int NOT NULL, orderdate date NOT NULL, empid int NOT NULL, custid varchar(10) NOT NULL, qty int NOT NULL, PRIMARY KEY(orderid,orderdate));
INSERT INTO rollup SELECT 1,'2010-01-02',3,'A',10; INSERT INTO rollup SELECT 2,'2010-04-02',2,'B',20; INSERT INTO rollup SELECT 3,'2010-05-02',1,'A',30; INSERT INTO rollup SELECT 4,'2010-07-02',3,'D',40; INSERT INTO rollup SELECT 5,'2011-01-02',4,'A',20; INSERT INTO rollup SELECT 6,'2011-01-02',3,'B',30; INSERT INTO rollup SELECT 7,'2011-01-02',1,'C',40; INSERT INTO rollup SELECT 8,'2009-01-02',2,'A',10; INSERT INTO rollup SELECT 9,'2009-01-02',3,'B',20;
首先做一个简单的一维聚合
1 2 3 4
SELECT YEAR(orderdate) year, SUM(qty) sum FROM rollup GROUP BY YEAR(orderdate) WITH ROLLUP;
结果为
和普通的 group by 差别不大,只是多了一个 (null,220),表示对所有的 year 再做一次聚合,即订单数量总和。
对单个唯独进行 rollup 操作只是可以在最后得到聚合的数据,对比 group by 语句并没有非常大的优势。
对多个维度进行 rollup 才能体现出 rollup 的优势:
(对 3 列进行层次的维度操作)
1 2 3 4
SELECT empid, custid, YEAR(orderdate) year, SUM(qty) sum FROM rollup GROUP BY empid,custid,YEAR(orderdate) WITH ROLLUP;
SELECT empid, custid, YEAR(orderdate) YEAR, SUM(qty) sum FROM rollup GROUP BY empid, custid, YEAR(orderdate) UNION SELECT empid, custid, NULL, SUM(qty) sum FROM rollup GROUP BY empid, custid UNION SELECT empid, NULL, NULL, SUM(qty) sum FROM rollup GROUP BY empid UNION SELECT NULL, NULL, NULL, SUM(qty) sum FROM rollup
虽然两者得到相同的结果,但是执行计划却不同
rollup 只需要一次表扫描操作就能得到全部结果,因此查询效率在此得到了极大的提升。
P.S.在使用 rollup 需要注意以下几方面
ORDER BY 不能在 rollup 中使用,两者为互斥关键字,如果使用,会抛出以下错误:Error Code:1221. Incorrect usage of CUBE/ROLLUP and ORDER BY
可以使用 LIMIT,但是因为不能使用 order by,所以阅读性下降,故大多数情况下无实际意义。
SELECT empid, custid, YEAR(orderdate) year, SUM(qty) sum from rollup GROUP BY empid, custid, YEAR(orderdate) WITH ROLLUP UNION SELECT empid, custid, YEAR(orderdate) year, SUM(qty) sum from rollup GROUP BY empid, YEAR(orderdate), custid WITH ROLLUP UNION SELECT empid, custid, YEAR(orderdate) year, SUM(qty) sum from rollup GROUP BY custid, YEAR(orderdate),empid WITH ROLLUP UNION SELECT empid, custid, YEAR(orderdate) year, SUM(qty) sum from rollup GROUP BY custid, empid, YEAR(orderdate) WITH ROLLUP UNION SELECT empid,custid,YEAR(orderdate) year, SUM(qty) sum from rollup GROUP BY YEAR(orderdate), empid, custid WITH ROLLUP UNION SELECT empid,custid,YEAR(orderdate) year, SUM(qty) sum from rollup GROUP BY YEAR(orderdate), custid, empid WITH ROLLUP;