LOD算法的全称是详细级别表达式(level of detail expressisons)。它主要是为了克服一些表达式之间的算子粒度不一致的问题。例如,我们在回答一个简单的问题的时候:我想知道每个人的身高与平均身高之间的差别。通常,为了得到结果,我们需要进行两步查询,第一步,查出所有人的平均身高:SELECT AVG(height) FROM humans ,假设该值为H; 第二步,将每个人的身高减去这个平均值: SELECT height - H FROM humans;
这是一个两步的过程,如果想使用一个表达式完成这个查询该怎么做呢?它的过程就会比较复杂:
SELECT all.height - avg.H
FROM humans as all
JOIN (SELECT AVG(height) as H FROM humans) as avg
而LOD就是相当于实现了后者的过程,以便用户在一个简单的表达式内就简单的可以实现这个需求: [身高]- {FIXED : AVG([身高])}
详细级别表达式可以解答非常多这类的问题,比如单日销售额和月总计销售额的占比如何,总售出超过100万元的产品是来自哪些订单……凡是明细粒度和聚合粒度不一致,但是却又需要比较的场景,我们都可以通过LOD简单的实现。
再举一个例子,有数的表格如下
浙江 | 杭州 | 100 |
浙江 | 宁波 | 150 |
江苏 | 南京 | 200 |
江苏 | 苏州 | 150 |
如上图,假设我们需要求省级别的总和,我们只需要做成如下
浙江 | 250 |
江苏 | 350 |
那如果我们需要做成
浙江 | 杭州 | 100 | 本省之和(250) |
浙江 | 宁波 | 150 | 本省之和(250) |
江苏 | 南京 | 200 | 本省之和(350) |
江苏 | 苏州 | 150 | 本省之和(350) |
该如何实现这个本省之和呢?
这就引入fixed做跨粒度计算,本省之和= {FIXED [省份]:SUM(额度)}
这样就相当于在省份的粒度上对额度求和了。这样也就容易计算各城市额度占省份之比等各类指标。
扩展阅读1:
假设我在省份的面前加上一个日期维度:
2019-8-1 | 浙江 | 杭州 | 100 | {FIXED [省份]:sum(额度)} =450 |
2019-8-1 | 浙江 | 宁波 | 150 | {FIXED [省份]:sum(额度)} =450 |
2019-8-2 | 浙江 | 杭州 | 200 | {FIXED [省份]:sum(额度)} =450 |
2019-8-1 | 江苏 | 南京 | 200 | {FIXED [省份]:sum(额度)} =200 |
可以看到这里的维度其实是不对了,因为我们要求杭州在8-1号的省占比,其实应该是100/(100+150)而不是100/(100+150+200)。
所以此时需要将计算字段改为{FIXED [日期],[省份]:SUM(额度)};
扩展阅读2:
由于fixed语法其实是利用了一个子查询,如
SELECT all.height - avg.H
FROM humans as all
JOIN (SELECT AVG(height) as H FROM humans) as avg
那么如果我在界面上添加了一个过滤器比如 性别筛选器=男,那么这个查询会变成什么样呢?如下:
SQL1:
SELECT all.height - avg.H
FROM humans where SEX="男" as all
JOIN (SELECT AVG(height) as H FROM humans) as avg
但其实我们需要求男性平均身高差其实应该是
SQL2:
SELECT all.height - avg.H
FROM humans where SEX="男" as all
JOIN (SELECT AVG(height) as H FROM humans where SEX="男" ) as avg
这个时候就需要将我们的性别筛选器的优先级提升,勾选其“优先筛选”才可以做到SQL2的效果。