12.20.1 Aggregate Function Descriptions
12.20.3 MySQL Handling of GROUP BY
ONLY_FULL_GROUP_BY
新建一张 sku 表并插入一些数据
DROP TABLE IF EXISTS `sku`;
CREATE TABLE `sku` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`goods_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '商品id',
`sku_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '规格名称',
`goods_price` bigint NULL DEFAULT NULL COMMENT '商品价格',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
INSERT INTO `sku` VALUES (1, 'a', '标准版', 100);
INSERT INTO `sku` VALUES (2, 'a', '标准版plus', 150);
INSERT INTO `sku` VALUES (3, 'b', '标准版', 120);
INSERT INTO `sku` VALUES (4, 'b', '标准版plus', 220);
INSERT INTO `sku` VALUES (5, 'a', '低配版', 80);
INSERT INTO `sku` VALUES (6, 'b', '低配版', 110);
当我们想要查询出不同goods_id最低价格的时候可以这么写
SELECT
goods_id,
min( goods_price )
FROM
sku
GROUP BY
goods_id
在此基础上,如果我们想要查询sku_name,SQL语句很有可能会采用这种写法
SELECT
goods_id,
sku_name,
min( goods_price )
FROM
sku
GROUP BY
goods_id
我们会得到一个1055错误:this is incompatible with sql_mode=only_full_group_by
> 1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'me.sku.sku_name' which is not functionally dependent on columns in GROUP BY clause;
> this is incompatible with sql_mode=only_full_group_by
查询 sql_mode 语句
SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;
例如,我的机器上是这两个mode,具体限制可以参考官方文档。
STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
设置sql_mode
SET GLOBAL sql_mode = 'modes';
SET SESSION sql_mode = 'modes';
Tips:有很多教程会让你去掉ONLY_FULL_GROUP_BY这一限制,这是不正确的做法,很有可能带来其他的问题。
问题1:查询错行
SELECT
goods_id,
sku_name,
min( goods_price )
FROM
sku
GROUP BY
goods_id
查询结果
很明显,价格为的sku_name为低配版,
正确的写法1(join):通过一个链接查询,用 最低价格跟 id 两个 字段来唯一匹配主表中的行记录即可。
SELECT
*
FROM
sku AS t1
INNER JOIN ( SELECT goods_id, min( goods_price ) AS mixPrice FROM sku GROUP BY goods_id ) AS t2 ON t1.goods_id = t2.goods_id
AND t1.goods_price = t2.mixPrice
SELECT
*
FROM
sku AS t1
WHERE
NOT EXISTS (
SELECT
goods_id,
goods_price
FROM
sku AS t2
WHERE
t1.goods_id = t2.goods_id
AND t1.goods_price > t2.goods_price)
如果理解:不存在 t1的价格 > t2的价格代表最终查询结果不会比t2全表中的大,也就是最小的数据。
如果实在理解不了实际环境中根据测试结果取即可。