我发现group by使用的“with rollup”选项非常有用。但它不符合“order by”条款。 有没有办法按我想要的方式订购以及计算小计?
CREATE TABLE `mygroup` (
`id` int(11) default NULL,
`country` varchar(100) default NULL
) ENGINE=MyISAM ;
INSERT INTO `mygroup` VALUES (1,'India'),(5,'India'),(8,'India'),(18,'China'),(28,'China'),(28,'China');
mysql>select country, sum(id) from mygroup group by country with rollup;
+---------+---------+
| country | sum(id) |
+---------+---------+
| China | 74 |
| India | 14 |
| NULL | 88 |
+---------+---------+
3 rows in set (0.00 sec)
mysql>select country, sum(id) as cnt from mygroup group by country order by cnt ;
+---------+------+
| country | cnt |
+---------+------+
| India | 14 |
| China | 74 |
+---------+------+
2 rows in set (0.00 sec)
mysql>select country, sum(id) as cnt from mygroup group by country with rollup order by cnt;
ERROR 1221 (HY000): Incorrect usage of CUBE/ROLLUP and ORDER BY
Expected Result:
+---------+------+
| country | cnt |
+---------+------+
| India | 14 |
| China | 74 |
| NULL | 88 |
+---------+---------+
3 rows in set (0.00 sec)
答案 0 :(得分:12)
尝试使用临时表
SELECT *
FROM
(
SELECT country, sum(id) as cnt
FROM mygroup GROUP BY country WITH rollup
) t
ORDER BY cnt;
本文可以帮助您link text
答案 1 :(得分:10)
您是否尝试过将订单放入分组?
SELECT country, SUM(id)
FROM mygroup
GROUP BY country DESC WITH ROLLUP;
应该返回:
+---------+---------+
| country | SUM(id) |
+---------+---------+
| India | 14 |
| China | 74 |
| NULL | 88 |
+---------+---------+
http://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html
答案 2 :(得分:3)
您可以尝试此查询:
SELECT country,id
FROM mygroup GROUP BY country ASC WITH ROLLUP
答案 3 :(得分:1)
使用两个子查询,如下所示:
-- 3. Filter the redundant rows. Don't use HAVING; it produces a redundant row
-- when there's only one country.
SELECT r2.country, r2.cnt
FROM (
-- 2. Save the ordering by giving each row an increasing serial number.
-- By grouping by serial numbers and country counts with rollup, the
-- ordering is preserved and rollup data is calculated.
SELECT (@s := @s + 1) AS sn, r1.country, SUM(r1.cnt) AS cnt
FROM (
-- 1. Calculate the country counts and order by them
SELECT country, SUM(id) AS cnt
FROM mygroup
GROUP BY 1
ORDER BY 2
) r1, (SELECT @s := 0) x
GROUP BY 1, 2 WITH ROLLUP
) r2
WHERE r2.country IS NOT NULL OR r2.sn IS NULL
结果应按cnt
排序,并在最后一行中使用小计:
+---------+------+
| country | cnt |
+---------+------+
| India | 14 |
| China | 74 |
| NULL | 88 |
+---------+------+
3 rows in set (0.00 sec)
答案 4 :(得分:0)
两个子查询解决方案不必要地复杂。您只需要一个,而无需序列号。
select country, cnt
from (
select
country,
sum(id) as cnt
from mygroup
group by country with rollup
) mygroup_with_rollup
order by country is null, cnt, country;
country is null
将汇总行放在末尾。
答案 5 :(得分:0)
似乎since 2017 MySQL具有GROUPING()函数。使用ORDER BY时可以使用。此外,GROUP BY和ORDER BY现在可以共存(您原来的问题的第三个查询不再引发错误),但是在尝试对数据进行排序时确实存在一些缺陷,通常只是将ROLLUP引发到表的顶部当使用DESC时,我将演示其他问题,然后说明如何解决。让我们用扳手来处理原始数据:
INSERT INTO `mygroup` VALUES (-8,'Kenya'),(-12,'Kenya');
使用上面显示的临时表方法,将在表中间出现NULL / ROLLUP的地方得到这些结果,这是另一个问题,可能甚至比到达顶部更糟:
+---------+------+
| country | cnt |
+---------+------+
| Kenya | -20 |
| India | 14 |
| NULL | 68 |
| China | 74 |
+---------+------+
我们可能不希望这样,使用新的关键字GROUPING(),我们可以先按项目的分组对项目进行排序,然后在每个组中按单独的列进行排序:
-- big numbers on bottom, middle-numbered ROLLUP last
SELECT country, SUM(id) AS cnt FROM mygroup
GROUP BY country WITH ROLLUP ORDER BY GROUPING(country), cnt ASC;
-- big numbers on top, middle-numbered ROLLUP still last
SELECT country, SUM(id) AS cnt FROM mygroup
GROUP BY country WITH ROLLUP ORDER BY GROUPING(country), cnt DESC;
(DESC的)结果:
+---------+------+
| country | cnt |
+---------+------+
| China | 74 |
| India | 14 |
| Kenya | -20 |
| NULL | 68 |
+---------+------+
GROUPING()方法是一个更新的版本,可为您提供所需的内容,并具有确保将ROLLUP显示在所需位置的附加优点。