深入浅出MySQL group by

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

在这里插入图片描述
正确的写法2(NOT EXISTS):

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全表中的大,也就是最小的数据。
如果实在理解不了实际环境中根据测试结果取即可。

你可能感兴趣的:(MySQL,mysql,数据库,java)