-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
分库分表:结果集处理——聚合函数(不含 Group By 子句) #179
Comments
设计
|
还有一个问题,如果是avg我们Aggregator之后用什么类型记录直接使用float64吗 |
关于数字方面的问题,我的看法是=。=直接用 Decimal,一了百了 |
只有 AVG 用 decimal 吧。其它好像都不涉及精度之类的问题 |
这里我不是很明白 Match 方法和 MatchInfo 的意义。我倾向于认为,用户在初始化 Merger 的时候要告诉你所有的列对应的聚合函数是什么,比如说: m := NewMerger(AggrInfoList)
type AggrInfo struct {
Func // 标记是 MIN,MAX 还是啥
name // 列名。比如说在 SELECT AVG(age) as avg_age 的时候应该传入 age。可以考虑在没有 AVG 的时候就直接使用第一个结果集的列名
typ reflect.Type
} 这意味着 Merger 能够知道每一列的含义。这里要考虑两个点:在没有 GROUP BY 的时候,所有的列都是聚合函数,但是在有 GROUP BY 的时候,还可以是 GROUP BY 的列。 Aggregator 的抽象我觉得是合适的。那么就近似于,遍历 AggreInfo,然后根据 Func 来调用对应的 Aggregator 实现来处理。但是有一个地方 Aggregator 的设计可能不太好用,就是 AVG。 基本逻辑是,如果你看到了FUNC 为 AVG,那么就要找到对应的 SUM 和 COUNT,然后计算一个平均值。这里会有问题,就是如果用户 SELECT AVG(age), COUNT(name),那么生成的实际SQL就得是 SELECT COUNT(ID), SUM(age), COUNT(name)。或者说你拿到的结果集就是这三个列。 但是用户在调用 Columns() 的时候,返回的应该是 AVG(age), COUNT(name);在进行 Next 或者 Scan 的时候应该也只有这两个。也就是说,NewMerger 传入的是预期的聚合函数,而结果集拿到的是分库分表之后实际的聚合函数。 只有 AVG 会有这种恶心的问题。那么进一步,在 AVG 的时候,用户还需要指定 COUNT 和 SUM 究竟在哪个列。比如说 AggreInfo { Func: AVG, name: avg_age, type: float64, countIndex: 2, sumIndex: 4}, 也就是说,计算这个 AVG 的COUNT 在 cols[2],SUM 在 cols[4]。在计算 AVG 的时候,我倾向于在发生 Scan 之前都是用 Decimal 来计算的,Scan 的时候再利用 ConvertAssign 来转类型。甚至于,如果为了简化代码,我认为所有的聚合函数都可以用 Decimal 来计算,然后在 Scan 的时候再转换为对应的类型。只不过因为别的聚合函数处理方式比较简单,所以不用 decimal 也可以。 从这里可以看到,AggreInfo 可能需要是接口,有三种实现:
那么对应的 Aggregator 也不是很合适了。Aggregate(..any) 这种设计处理不了 AVG 的情况。 |
有一个问题我们从sql.Rows拿到对应的聚合函数的列名是怎么样的,以max(id)的形态在没有别名的情况下是id,还是说是Max(id)这种 |
是 Max(id) 这种。这里其实我觉得依赖于列名可能不是特别好。 我倾向于认为用顺序会比较好。也就是你在 []map[string]any 这里,不如就直接按照顺序传下去 [][]any。 之前我记得我们在排序里面用的也是下标而不是列名,所以这里可以考虑保持一致。不然的话就连排序那边也改过来用列名。 这个设计我觉得问题不大,不过在 AggreInfo 里面,我不建议这么组合,直接实现这个接口就可以。 你可以有 AggreInfo, AvgInfo, ColumnInfo 什么的 |
仅限中文
使用场景
聚合函数常见的有:
当然在这个例子里面,COUNT(ID) 只是一个例子,只是为了计算有多少条数据。
聚合函数和 GROUP BY
聚合函数在有 GROUP BY 和没有 GROUP BY 子句下是很不一样的。在有 GROUP BY 的场景下,聚合函数计算的是组内的聚合函数。
例如说 SELECT AVG(age) FROM user GROUP BY gender,这个 SQL 是计算按照性别划分的平均年龄,也就是说会有两个结果:男性平均年龄和女性平均年龄。
所以实际上在处理有 GROUP BY 子句的时候,比如说 SELECT AVG(age) FROM user GROUP BY gender 会变成:
注意,这个时候在 SELECT 子句里面必须带上 GROUP BY 的列,也就是 gender,不然我们不知道如何处理。
那么假如说我们在两张表里面拿到四条数据:
那么实际上计算的结果是 <(123+233)/(3+5), male> 和 <(125+225)/(2+7), female>。
这里我们可以总结出来:
第二个点,手动进行分组是一个很麻烦的点。它分成两种情况:
因此 GROUP BY 会带来很多额外的复杂度。因此在当前 issue 下,认为它必然是不带 GROUP BY 的,等后面我们再创建 issue 来支持带 GROUP BY 的。
多个聚合函数合并使用
很显然,用户可以在一个查询语句里面查询多个聚合函数的值,比如说 SELECT MIN(age), MAX(age) FROM xxx。那么我们也需要考虑支持这种场景。
设计
MIN、MAX、SUM和COUNT
这四个的实现非常简单额,每一个都是一个单独的列。在我们
其它
The text was updated successfully, but these errors were encountered: