Версия MySql: 5.7.18-15-журнал,

Мой одноклассник задал вопрос:

SELECT 
  COUNT(1) Counts, 
  IFNULL((SELECT SUM(c.RealMoney) FROM PayRecord c WHERE a.id=c.orderid), 0) money
FROM `Order` a
WHERE a.UserId ='not exists user id';

Он получил результат:

Считает: 0 денег 8000

, а он спросил почему ??? нет записи, зачем деньги ???

Я попробовал и обнаружил, что это похоже на ошибку, например:

SELECT
  COUNT(1) Counts, 
  IFNULL((SELECT c.RealMoney FROM PayRecord c WHERE a.id=c.orderid), 0) money
FROM `Order` a
WHERE  a.id='bc7ba7ed-44f2-4686-b5ae-df65e8cc566f';

Возвращение

Счетов: 1 денег: 8622

SELECT 
  COUNT(1) Counts, 
  IFNULL((SELECT SUM(c.RealMoney) FROM PayRecord c WHERE a.id=c.orderid), 0) money
FROM `Order` a
WHERE a.UserId ='not exists user id';

Возвращение

Счетов: 0 денег: 8622

Кажется, первый sql будет кеширован,
а второй sql будет использовать этот кеш ...

DDL как:

CREATE TABLE `Order` (
  `Id` char(36) NOT NULL ,
  `UserId` char(36) NOT NULL ,
  ......,
  PRIMARY KEY (`Id`,`CreateTime`),
  KEY `idx_RestId` (`RestId`),
  KEY `idx_CreateTime` (`CreateTime`),
  KEY `idx_UserId` (`UserId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 
/*!50500 PARTITION BY RANGE  COLUMNS(CreateTime)
(
 PARTITION p201712 VALUES LESS THAN ('2018-01-01') ENGINE = InnoDB,
 PARTITION p201801 VALUES LESS THAN ('2018-02-01') ENGINE = InnoDB) */


CREATE TABLE `PayRecord` (
  `Id` char(36) NOT NULL ,
  `OrderId` char(36) NOT NULL ,
  `RealMoney` int(11) NOT NULL ,
  .......
  PRIMARY KEY (`Id`,`CreateTime`),
  KEY `idx_OrderId` (`OrderId`),
  KEY `idx_PayId` (`PayId`),
  KEY `idx_CreateTime` (`CreateTime`),
  KEY `idx_BrandId_RestId` (`BrandId`,`RestId`),
  KEY `idx_RestId` (`RestId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50500 PARTITION BY RANGE  COLUMNS(CreateTime)
(
 PARTITION p201712 VALUES LESS THAN ('2018-01-01') ENGINE = InnoDB,
 PARTITION p201801 VALUES LESS THAN ('2018-02-01') ENGINE = InnoDB) */

И мой вопрос был: почему Count не возвращает запись, но IFNULL имеет значение ???

0
youbl 27 Фев 2018 в 10:19

1 ответ

Лучший ответ

Логика того, что вы видите то, что наблюдаете, состоит в том, что COUNT - это агрегатная функция. При использовании без GROUP BY он вернет счетчик по всей таблице. Также важно, что он всегда будет возвращать одну запись, даже если в реальной таблице нет записей. Использование COUNT в предложении select также означает, что могут отображаться только другие агрегатные функции или скалярные константы. Причина, по которой вы видите денежную сумму, заключается в том, что она поступает из подзапроса, который генерирует одно скалярное значение.

Хотя это может быть трудно отделить друг от друга, это определенно не ошибка MySQL.

2
Tim Biegeleisen 27 Фев 2018 в 10:30