MySQL派生列未被识别为功能依赖列

ljo96ir5  于 2023-10-15  发布在  Mysql
关注(0)|答案(2)|浏览(122)

下表:

CREATE TABLE `Example` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `properties` json DEFAULT NULL,
  `hash` binary(20) GENERATED ALWAYS AS (unhex(sha(`properties`))) STORED,
  PRIMARY KEY (`id`),
  KEY `hash` (`hash`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

hash从列properties导出。在the docs{properties} -> {hash}的命名中,
同样来自关于handling of GROUP BY的文档,有以下内容:
SQL:1999和更高版本允许根据可选特性T301的非聚集,如果它们在功能上依赖于GROUP BY列:如果name和custid之间存在这种关系,则查询是法律的。例如,如果custid是customers的主键,
但是,尽管如此,以下查询仍返回错误(表中不需要数据即可重现此错误):

SELECT `properties` from `Example` GROUP BY `hash`;

误差
SELECT列表的表达式#1不在GROUP BY子句中,并且包含功能上dispatch.Example.properties不依赖于GROUP BY子句中的列的非聚合列“www.example.com”;这与sql_mode=only_full_group_by不兼容
该错误表示该列在功能上不相关。这可能是因为查询分析器不假定SHA函数返回的值是确定性的。可能?哈希冲突的可能性会扼杀整个想法吗?
如果我仍然必须对properties列应用聚合函数来填充结果,那么哈希值就没有那么有用了。有没有一种方法可以向MySQLAssert存在函数依赖?
如果做不到这一点,那么说“只要给予我任何匹配行中的属性”而不涉及比较properties记录(这是哈希的重点)的最佳方法是什么?我最好的办法是在窗口函数中使用FIRST,但这感觉很不好。

yacmzcpb

yacmzcpb1#

我错的是依赖的方向;与以上示例

Select `hash` FROM `Example` GROUP BY `properties`

工作正常,因为hash依赖于properties
因为在我的例子中,hash的存在仅仅是为了更有效地索引和分组,所以上面的方法不是一个选择。
docs for aggregating functions中没有提到的是函数ANY_VALUE,它不可预测地返回来自分组行之一的值。因为我知道这两列是等价的,所以我不关心properties选择哪一行。
生成的工作查询是:

SELECT ANY_VALUE(`properties`) from `Example` GROUP BY `hash`;
e37o9pze

e37o9pze2#

它与使用派生列无关。
函数依赖在按主键分组和其他一些情况下有效。但在你的问题中,你的查询不符合任何情况。实际上,properties在功能上并不依赖于hashproperties可能有多个不同的值,它们在hash中具有相同的值)。
https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html
SQL:1999和更高版本允许根据可选特性T301的非聚集,如果它们在功能上依赖于GROUP BY列:如果name和custid之间存在这种关系,则查询是法律的。例如,如果custid是客户的主键,情况就是这样。
您可以测试自己的示例表来证明这一点。按id(表的主键)分组,不会得到错误:

mysql> SELECT `properties` from `Example` GROUP BY `id`;
Empty set (0.00 sec)

此外,如果添加的列不是派生列,则仍然不能依赖函数依赖性,无论它们是唯一的还是非唯一的。

mysql> alter table example 
  add column u int, 
  add unique key (u), 
  add column n int, 
  add key (n);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SELECT `properties` from `Example` GROUP BY `u`;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.Example.properties' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

mysql> SELECT `properties` from `Example` GROUP BY `n`;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.Example.properties' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

回复您的评论:
我错了这不仅仅是主键,还有MySQL可以检测函数依赖关系的其他情况(我已经编辑了我的答案顶部附近的语句)。但不是你在第一个问题中提到的情况。
我找到了一个手册页面,它更完整地描述了MySQL对函数依赖的支持:https://dev.mysql.com/doc/refman/8.0/en/group-by-functional-dependence.html

相关问题