the*_*let 7 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;
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
期望的输出:
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
Run Code Online (Sandbox Code Playgroud)
提前致谢!
与解决该问题COALESCE/IFNULL仍然返回NULL为WITH ROLLUP占位符,你需要GROUP BY的表的列名,而不是别名列表达式。
该问题是由在别GROUP BY名列表达式上指定的子句引起的,因为在处理列表达式之后分配别名。
导致WITH ROLLUP NULL占位符不在要评估的记录集中COALESCE。
含义的别名DEALER,SERVICE_ADVISOR在GROUP BY不存在,直到后 IFNULL/COALESCE已经执行。有关更多详细信息,请参阅 MySQL处理GROUP BY。
示例 数据库小提琴
CREATE TABLE foo (
`amount` INTEGER,
`created` INTEGER
);
INSERT INTO foo
(`amount`, `created`)
VALUES
('1', '2019'),
('2', '2019');
Run Code Online (Sandbox Code Playgroud)
查询 #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 | |
Run Code Online (Sandbox Code Playgroud)
查询 #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 |
Run Code Online (Sandbox Code Playgroud)
示例 数据库小提琴
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;
Run Code Online (Sandbox Code Playgroud)
查询 #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 |
Run Code Online (Sandbox Code Playgroud)
查询 #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 |
Run Code Online (Sandbox Code Playgroud)
启用MySQL 5.7+ 和ONLY_FULL_GROUP_BY 后,
GROUP BY子句中未指定的选定非聚合列将失败。这意味着以下查询不会按预期工作:DB-FiddleRun Code Online (Sandbox Code Playgroud)SELECT COALESCE(YEAR(foo), 'foo') /* ... */ GROUP BY YEAR(foo) WITH ROLLUP -> ER_WRONG_FIELD_WITH_GROUP: Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.foo_bar.foo' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
COALESCE,IFNULL,IF(... IS NULL)和CASE WHEN ... IS NULL功能类似。哪里IFNULL是 MySQL 的专有,是功能较弱的COALESCE. 由于COALESCE可以接受两个以上的参数进行检查NULL,因此返回第一个non-NULL值。Run Code Online (Sandbox Code Playgroud)mysql> SELECT COALESCE(NULL, NULL, 1, NULL); -> 1 mysql> SELECT IFNULL(NULL, 1); -> 1 mysql> SELECT IF(NULL IS NULL, 1, ''); -> 1 mysql> SELECT CASE WHEN NULL IS NULL THEN 1 END; -> 1
GROUP BY作为别名或列名的可为空的列将导致NULL值显示为WITH ROLLUP占位符。这适用WITH ROLLUP于一般使用。例如如果users.name可以返回NULL。数据库小提琴Run Code Online (Sandbox Code Playgroud)| DEALER | SERVICE_ADVISOR | COMPLETED | | ------ | --------------- | --------- | | Foo | TOTAL | 1 | | Foo | Jane Doe | 1 | | Foo | John Doe | 1 | | Foo | TOTAL | 3 | | GROUP | TOTAL | 3 |
NULL显示列值为确保不会意外包含可为空的列,您需要在条件中指定以排除它们。
示例 数据库小提琴
CREATE TABLE foo (
`amount` INTEGER,
`created` INTEGER
);
INSERT INTO foo
(`amount`, `created`)
VALUES
('1', '2019'),
('2', '2019');
Run Code Online (Sandbox Code Playgroud)
结果
| DEALER | SERVICE_ADVISOR | COMPLETED |
| ------ | --------------- | --------- |
| Foo | Jane Doe | 1 |
| Foo | John Doe | 1 |
| Foo | TOTAL | 2 |
| GROUP | TOTAL | 2 |
Run Code Online (Sandbox Code Playgroud)
既然
LEFT JOIN是用在vcrs表上,IS NOT NULL就必须应用于WHERE子句,而不是ON子句。作为不匹配标准的LEFT JOIN回报NULL。为了规避这个问题,使用 anINNER JOIN将结果集限制为仅具有匹配ON条件的结果集。
/* ... */
INNER JOIN users
ON users.id = vcrs.uid
AND users.name IS NOT NULL
/* ... */
WHERE vcrs.vcrSubStatus = 4
GROUP BY usergroups.name, users.name
WITH ROLLUP;
Run Code Online (Sandbox Code Playgroud)
NULL列值要显式包含可为空的列值,而不复制WITH ROLLUP占位符名称,您需要利用派生表子查询将该NULL值替换为文本值。
示例 数据库小提琴
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 | |
Run Code Online (Sandbox Code Playgroud)
结果
| DEALER | SERVICE_ADVISOR | COMPLETED |
| ------ | --------------- | --------- |
| Foo | Jane Doe | 1 |
| Foo | John Doe | 1 |
| Foo | NULL | 1 |
| Foo | TOTAL | 3 |
| GROUP | TOTAL | 3 |
Run Code Online (Sandbox Code Playgroud)
您还可以'NULL'根据需要选择替换文本占位符,甚至将其显示为NULL.
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 |
Run Code Online (Sandbox Code Playgroud)
我只晚了 2 年,但是因为我遇到了与@the_gimlet 相同的问题,所以我想我会发布答案。
所以不知道这是 mySQL 版本控制还是什么,但是使用 mysql 5.6 我遇到了同样的问题...... ifnull 不会替换汇总“nulls”。
只需通过将汇总作为子查询并在主选择中执行 ifnulls 来解决此问题...重复选择很烦人,但它有效!
例如上面的例子
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);
Run Code Online (Sandbox Code Playgroud)
你想要这样的东西吗?
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;
Run Code Online (Sandbox Code Playgroud)
测试:
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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7117 次 |
| 最近记录: |