ecodeclub / eorm

简单 ORM 框架
Apache License 2.0
194 stars 64 forks source link

eorm: Distinct 关键字支持 #113

Closed flycash closed 1 year ago

flycash commented 1 year ago

仅限中文

使用场景

使用 Distinct 关键字主要有两个地方:

第一种形态最为常见,而第二种形态则不那么常见,也是我们设计和实现的一个难点。

行业分析

实际上,在 Distinct 支持上有几种风格:

而对于第二种形态来说,大多数 ORM 框架都是在解决 Select xxx 列的时候一并解决的。普遍来说,他们的方案是:

db.Select("COUNT(DISTINTCT id)")

也就是用字符串来作为输入,那么在这种情况下,用户可以输入任意的东西,自然也就包含了带 Distinct 关键字的聚合函数。

可行方案

按照行业惯例和我们已有的设计,第一种形态我们可以直接添加一个新的 Distinct 方法:

func (s *Selector) Distinct()  *Selector {

}

执行了这个调用之后生成的 Select 语句,会带上 DISTINCT 关键字:SELECT DISTINCT xxx...

而对于第二种形态来说,我们有两种选择: 第一种, 什么也不做。因为目前用户可以直接使用我们的 RawExpr 来达成目标:`s.Select(Raw("COUNT(DISTINCT id)"))

第二种,我们考虑帮助用户解决问题,那么也有两条路:


// 我们自己内部利用 RawExpr 来封装一下。在这里 col 必须是数据库内部的列名
func CountDistinct(col...string) RawExpr {
    return Raw("COUNT DISTINCT cols....")
}

// 这种设计形态下, col 实际上是字段名,同时我们可以对 col 进行校验,确保用户不会输错。
func CountDistinct(col string) Aggregate {
     return Aggregate{
              fn: "COUNT",
              arg: col,
              distinct: true // 这是在 Aggregate 中新加的字段。这一类的 Aggregate 才会设置为 true
     }
}

当我们要做的时候,就需要对 Count, Avg, Sum 都提供一个对应的方法,而 Max 和 Min 则不需要。

其它

你需要验证一个东西,能不能使用类似的 SELECT 语句:

SELECT * FROM xx HAVING COUNT(DISTINCT id) > 10

即在 HAVING 子句中使用这种东西。

此外:

你使用的是 eorm 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

juniaoshaonian commented 1 year ago

大佬这个我试试哇

flycash commented 1 year ago

116