下表:
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
,但这感觉很不好。
2条答案
按热度按时间yacmzcpb1#
我错的是依赖的方向;与以上示例
工作正常,因为
hash
依赖于properties
。因为在我的例子中,
hash
的存在仅仅是为了更有效地索引和分组,所以上面的方法不是一个选择。在docs for aggregating functions中没有提到的是函数
ANY_VALUE
,它不可预测地返回来自分组行之一的值。因为我知道这两列是等价的,所以我不关心properties
选择哪一行。生成的工作查询是:
e37o9pze2#
它与使用派生列无关。
函数依赖在按主键分组和其他一些情况下有效。但在你的问题中,你的查询不符合任何情况。实际上,
properties
在功能上并不依赖于hash
(properties
可能有多个不同的值,它们在hash
中具有相同的值)。https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html
SQL:1999和更高版本允许根据可选特性T301的非聚集,如果它们在功能上依赖于GROUP BY列:如果name和custid之间存在这种关系,则查询是法律的。例如,如果custid是客户的主键,情况就是这样。
您可以测试自己的示例表来证明这一点。按
id
(表的主键)分组,不会得到错误:此外,如果添加的列不是派生列,则仍然不能依赖函数依赖性,无论它们是唯一的还是非唯一的。
回复您的评论:
我错了这不仅仅是主键,还有MySQL可以检测函数依赖关系的其他情况(我已经编辑了我的答案顶部附近的语句)。但不是你在第一个问题中提到的情况。
我找到了一个手册页面,它更完整地描述了MySQL对函数依赖的支持:https://dev.mysql.com/doc/refman/8.0/en/group-by-functional-dependence.html