MYSQL - ROLLUP - 用SUBTOTAL和TOTAL替换NULL

时间:2014-08-22 09:32:07

标签: mysql rollup totals ifnull

我曾尝试使用IFNULL来替换ROLLUP返回的小数字和总计的NULL字段,但它似乎没有工作。

查询:

select IFNULL(usergroups.name, 'GROUP') AS DEALER,
IFNULL(users.name, 'TOTAL') AS SERVICE_ADVISOR,
COUNT(DISTINCT vcrs.uid) AS COMPLETED,
..........
..........
and vcrs.vcrSubStatus = 4
group by DEALER, SERVICE_ADVISOR with ROLLUP;

输出:

DEALER          SERVICE_ADVISOR COMPLETED   IDENTIFIED  AUTHORISED
Aston Martin    Chris           3           664.56      0
Aston Martin    Graham          6           0           0
Aston Martin    (NULL)          15          664.56      0
Bentley         Sukraj          1           0           0
Bentley         Terry           4           0           0
Bentley         (NULL)          5           0           0
Jaguar          Emma            10          2448        1224
Jaguar          Paul            1           0           0
Jaguar          Simon           7           2754        918
Jaguar          (NULL)          18          5202        2142
(NULL)          (NULL)          2611        96591.62    42130.14

期望的输出:

DEALER          SERVICE_ADVISOR COMPLETED   IDENTIFIED  AUTHORISED
Aston Martin    Chris           3           664.56      0
Aston Martin    Graham          6           0           0
Aston Martin    TOTAL           15          664.56      0
Bentley         Sukraj          1           0           0
Bentley         Terry           4           0           0
Bentley         TOTAL           5           0           0
Jaguar          Emma            10          2448        1224
Jaguar          Paul            1           0           0
Jaguar          Simon           7           2754        918
Jaguar          TOTAL           18          5202        2142
GROUP           TOTAL           2611        96591.62    42130.14

提前致谢!

4 个答案:

答案 0 :(得分:3)

你想要这样的东西吗?

SELECT COALESCE(usergroups.name, 'GROUP') AS DEALER,
COALESCE(users.name, IF(usergroups.name IS NULL, 'TOTAL', 'SUBTOTAL')) AS SERVICE_ADVISOR,
COUNT(DISTINCT vcrs.uid) AS COMPLETED,
..........
..........
AND vcrs.vcrSubStatus = 4
GROUP BY DEALER, SERVICE_ADVISOR with ROLLUP;

测试:

mysql;root@localhost(playground)> select * from t;
+------+----------+-------+--------+
| id   | car      | state | tstamp |
+------+----------+-------+--------+
|    1 | toyota   | new   |   1900 |
|    2 | toyota   | old   |   1950 |
|    3 | toyota   | scrap |   1980 |
|    4 | mercedes | new   |   1990 |
|    5 | mercedes | old   |   2010 |
|    6 | tesla    | new   |   2013 |
+------+----------+-------+--------+
6 rows in set (0.04 sec)

mysql;root@localhost(playground)> select car, sum(tstamp) from t group by car with rollup;
+----------+-------------+
| car      | sum(tstamp) |
+----------+-------------+
| mercedes |        4000 |
| tesla    |        2013 |
| toyota   |        5830 |
| NULL     |       11843 |
+----------+-------------+
4 rows in set (0.03 sec)

mysql;root@localhost(playground)> select coalesce(car, 'huhu'), sum(tstamp) from t group by car with rollup;
+-----------------------+-------------+
| coalesce(car, 'huhu') | sum(tstamp) |
+-----------------------+-------------+
| mercedes              |        4000 |
| tesla                 |        2013 |
| toyota                |        5830 |
| huhu                  |       11843 |
+-----------------------+-------------+
4 rows in set (0.00 sec)

答案 1 :(得分:2)

我只有两年太晚了,但是因为我遇到了与@the_gimlet相同的问题,我以为我会发布答案。

所以不知道这是一个mySQL版本还是什么,但是使用mysql 5.6我得到了同样的问题... ifnull不会替换汇总'nulls'。

简单地通过使你的汇总成为子查询来解决这个问题,并在主选择中执行ifnulls ...烦恼重复选择,但是它有效!

e.g。例如上面

SELECT 
  IFNULL(`DEALER`, 'GROUP') AS DEALER,
  IFNULL(`SERVICE ADVISOR`, 'TOTAL') AS SERVICE_ADVISOR,
  `COMPLETED`,
  ..........
FROM (SELECT 
            usergroups.name AS DEALER,
            users.name AS SERVICE_ADVISOR,
            COUNT(DISTINCT vcrs.uid) AS COMPLETED,
            ..........
  AND       vcrs.vcrSubStatus = 4
  GROUP BY  DEALER, SERVICE_ADVISOR with ROLLUP;

答案 2 :(得分:1)

此问题是由于列别名的GROUP BY段在处理行后 被执行以创建要分组的别名值引起的。

结果; NULL不在记录集中,IFNULL/COALESCE可以用来验证。

示例 DB Fiddle

CREATE TABLE foo (
  `amount` INTEGER,
  `created` INTEGER
);

INSERT INTO foo
  (`amount`, `created`)
VALUES
  ('1', '2019'),
  ('2', '2019');

查询#1

SELECT
    SUM(amount) AS amounts,
    COALESCE(created, 'Total') AS created_coalesce
FROM foo
GROUP BY created_coalesce WITH ROLLUP;

| amounts | created_coalesce |
| ------- | ---------------- |
| 3       | 2019             |
| 3       |                  |

要解决COALESCE/IFNULL的问题,您需要GROUP BY表列名而不是已处理的别名。

另一个需要注意的问题是MySQL 5.7和ONLY_FULL_GROUP_BY,这会导致GROUP BY中未指定的选定非聚合列失败。因此SELECT COALESCE(YEAR(foo), 'foo') GROUP BY YEAR(foo) WITH ROLLUP无法正常工作。

查询#2

SELECT
    SUM(amount) AS amounts,
    COALESCE(created, 'Total') AS created_coalesce
FROM foo
GROUP BY foo.created WITH ROLLUP;

| amounts | created_coalesce |
| ------- | ---------------- |
| 3       | 2019             |
| 3       | Total            |

针对您的特定问题

示例 DB-Fiddle

SELECT
    COALESCE(usergroups.name, 'GROUP') AS DEALER,
    COALESCE(users.name, 'TOTAL') AS SERVICE_ADVISOR,
    COUNT(DISTINCT vcrs.uid) AS COMPLETED,
#...
GROUP BY usergroups.name, users.name WITH ROLLUP;

查询#1

SELECT
    COALESCE(usergroups.name, 'GROUP') AS DEALER,
    COALESCE(users.name, 'TOTAL') AS SERVICE_ADVISOR,
    COUNT(DISTINCT vcrs.uid) AS COMPLETED
#...
GROUP BY DEALER, SERVICE_ADVISOR WITH ROLLUP;

| DEALER | SERVICE_ADVISOR | COMPLETED |
| ------ | --------------- | --------- |
| Foo    | Jane Doe        | 1         |
| Foo    | John Doe        | 1         |
| Foo    |                 | 2         |
|        |                 | 2         |

查询#2

SELECT
    COALESCE(usergroups.name, 'GROUP') AS DEALER,
    COALESCE(users.name, 'TOTAL') AS SERVICE_ADVISOR,
    COUNT(DISTINCT vcrs.uid) AS COMPLETED
#...
GROUP BY usergroups.name, users.name WITH ROLLUP;

| DEALER | SERVICE_ADVISOR | COMPLETED |
| ------ | --------------- | --------- |
| Foo    | Jane Doe        | 1         |
| Foo    | John Doe        | 1         |
| Foo    | TOTAL           | 2         |
| GROUP  | TOTAL           | 2         |

作为旁注COALESCEIFNULLCASE WHEN IS NULL的功能都相似。其中IFNULL是MySQL专有的,是COALESCE的功能较弱的替代品。由于COALESCE可以接受两个以上的参数来检查NULL,例如COALESCE(NULL, NULL, NULL, 1)

答案 3 :(得分:0)

您正在寻找的是案例陈述。 您所说的是,在某种情况下,将找到的值替换为指定的值。您可以使用多个when / then语句,具体取决于您希望替换的自定义方式。

select IFNULL(usergroups.name, 'GROUP') AS DEALER,
case when(users.name is null) then 'TOTAL' else users.name end AS SERVICE_ADVISOR,
COUNT(DISTINCT vcrs.uid) AS COMPLETED,
..........
..........
and vcrs.vcrSubStatus = 4
group by DEALER, SERVICE_ADVISOR with ROLLUP;