SQL 如果表定义为 MyISAM 或 InnoDB,查询将以不同方式计算 COUNT(*)
SQL query evaluates COUNT(*) differently if tables are defined as MyISAM or InnoDB
我正在 运行建立一个 MySQL 数据库。
我有以下脚本:
DROP TABLE IF EXISTS `org_apiinteg_assets`;
DROP TABLE IF EXISTS `assessmentinstances`;
CREATE TABLE `org_apiinteg_assets` (
`id` varchar(20) NOT NULL default '0',
`instance_id` varchar(20) default NULL,
PRIMARY KEY (`id`)
) ENGINE= MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=1;
CREATE TABLE `assessmentinstances` (
`id` varchar(20) NOT NULL default '0',
`title` varchar(180) default NULL,
PRIMARY KEY (`id`)
) ENGINE= MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=1;
INSERT INTO assessmentinstances(id, title) VALUES ('14026lvplotw6','One radio question survey');
INSERT INTO org_apiinteg_assets(id, instance_id) VALUES ('8kp9wgx43jflrgjfe','14026lvplotw6');
看起来像这样
assessmentinstances
+---------------+---------------------------+
| id | title |
+---------------+---------------------------+
| 14026lvplotw6 | One radio question survey |
+---------------+---------------------------+
org_apiinteg_assets
+-------------------+---------------+
| id | instance_id |
+-------------------+---------------+
| 8kp9wgx43jflrgjfe | 14026lvplotw6 |
+-------------------+---------------+
然后我有以下查询(我将其简化为最简单的失败查询)
SELECT ai.id, COUNT(*) AS `count`
FROM assessmentinstances ai, org_apiinteg_assets a
WHERE a.instance_id = ai.id
AND ai.id = '14026lvplotw6'
AND a.id != '8kp9wgx43jflrgjfe';
当我 运行 查询时,我得到这个
null, 0
到目前为止,一切都很好。现在,这是我的问题,当我再次使用 ENGINE=InnoDB
而不是 ENGINE=MyISAM
和 运行 重新创建两个表时,我得到了这个:
'14026lvplotw6','0'
所以有两件事让我感到困惑:
- 为什么我没有得到相同的结果?
- 在第二种情况下,
COUNT(*)
return 0 怎么可能是行的 returns 值,因此应该是 1?
我迷路了,如果有人能向我解释这种行为,我将不胜感激。
编辑:
有趣的是,如果我在查询末尾添加 GROUP BY ai.id
,它在这两种情况下都工作正常并且 return 没有行。
发生这种情况是因为您使用的聚合函数没有 GROUP BY
..在这种情况下,非聚合列的结果是不可预测的..(通常显示查询期间遇到的第一个值)
尝试添加 GROUP BY
SELECT ai.id, COUNT(*) AS `count`
FROM assessmentinstances ai, org_apiinteg_assets a
WHERE a.instance_id = ai.id
AND a.id != '8kp9wgx43jflrgjfe'
AND ai.id = '14026lvplotw6'
GROUP BY ai.id;
请记住,在 SQL 中弃用了在 group by 中未提及的列的情况下使用聚合,并且在大多数数据库和 mysql 的更新版本中是不允许的(从 5.7 开始)
EXPLAIN SELECT
对于 MyISAM returns:Impossible WHERE noticed after reading const tables
。所以 MyISAM 根本不处理任何数据。
对于 InnoDB,有两行 EXPLAIN
结果:一行 Using Index
和一行 Using where
。因此,正在扫描 InnoDB 数据,并且由于没有为第一列指定聚合函数并且 AFAIK 没有指定在这种情况下应该发生什么,所以它的一些位会滑入输出。如果直接指定一些聚合函数,那么if there are no matching rows, it will return NULL。因此,例如,SELECT min(ai.id), COUNT(*) ...
将 return NULL, 0
.
我正在 运行建立一个 MySQL 数据库。
我有以下脚本:
DROP TABLE IF EXISTS `org_apiinteg_assets`;
DROP TABLE IF EXISTS `assessmentinstances`;
CREATE TABLE `org_apiinteg_assets` (
`id` varchar(20) NOT NULL default '0',
`instance_id` varchar(20) default NULL,
PRIMARY KEY (`id`)
) ENGINE= MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=1;
CREATE TABLE `assessmentinstances` (
`id` varchar(20) NOT NULL default '0',
`title` varchar(180) default NULL,
PRIMARY KEY (`id`)
) ENGINE= MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=1;
INSERT INTO assessmentinstances(id, title) VALUES ('14026lvplotw6','One radio question survey');
INSERT INTO org_apiinteg_assets(id, instance_id) VALUES ('8kp9wgx43jflrgjfe','14026lvplotw6');
看起来像这样
assessmentinstances
+---------------+---------------------------+
| id | title |
+---------------+---------------------------+
| 14026lvplotw6 | One radio question survey |
+---------------+---------------------------+
org_apiinteg_assets
+-------------------+---------------+
| id | instance_id |
+-------------------+---------------+
| 8kp9wgx43jflrgjfe | 14026lvplotw6 |
+-------------------+---------------+
然后我有以下查询(我将其简化为最简单的失败查询)
SELECT ai.id, COUNT(*) AS `count`
FROM assessmentinstances ai, org_apiinteg_assets a
WHERE a.instance_id = ai.id
AND ai.id = '14026lvplotw6'
AND a.id != '8kp9wgx43jflrgjfe';
当我 运行 查询时,我得到这个
null, 0
到目前为止,一切都很好。现在,这是我的问题,当我再次使用 ENGINE=InnoDB
而不是 ENGINE=MyISAM
和 运行 重新创建两个表时,我得到了这个:
'14026lvplotw6','0'
所以有两件事让我感到困惑:
- 为什么我没有得到相同的结果?
- 在第二种情况下,
COUNT(*)
return 0 怎么可能是行的 returns 值,因此应该是 1?
我迷路了,如果有人能向我解释这种行为,我将不胜感激。
编辑:
有趣的是,如果我在查询末尾添加 GROUP BY ai.id
,它在这两种情况下都工作正常并且 return 没有行。
发生这种情况是因为您使用的聚合函数没有 GROUP BY
..在这种情况下,非聚合列的结果是不可预测的..(通常显示查询期间遇到的第一个值)
尝试添加 GROUP BY
SELECT ai.id, COUNT(*) AS `count`
FROM assessmentinstances ai, org_apiinteg_assets a
WHERE a.instance_id = ai.id
AND a.id != '8kp9wgx43jflrgjfe'
AND ai.id = '14026lvplotw6'
GROUP BY ai.id;
请记住,在 SQL 中弃用了在 group by 中未提及的列的情况下使用聚合,并且在大多数数据库和 mysql 的更新版本中是不允许的(从 5.7 开始)
EXPLAIN SELECT
对于 MyISAM returns:Impossible WHERE noticed after reading const tables
。所以 MyISAM 根本不处理任何数据。
对于 InnoDB,有两行 EXPLAIN
结果:一行 Using Index
和一行 Using where
。因此,正在扫描 InnoDB 数据,并且由于没有为第一列指定聚合函数并且 AFAIK 没有指定在这种情况下应该发生什么,所以它的一些位会滑入输出。如果直接指定一些聚合函数,那么if there are no matching rows, it will return NULL。因此,例如,SELECT min(ai.id), COUNT(*) ...
将 return NULL, 0
.