首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >SQL别裁新解:SUM OVER窗口函数 vs. Tableau Total表计算

SQL别裁新解:SUM OVER窗口函数 vs. Tableau Total表计算

作者头像
Tableau喜乐君
发布2026-07-08 20:22:09
发布2026-07-08 20:22:09
50
举报
文章被收录于专栏:Tableau喜乐君Tableau喜乐君

Tableau Visionary | Tableau Ambassdor

发布日期:2026年02月

在数据分析的日常工作中,我们经常会遇到这类需求:“既要看当前维度的聚合度量,又要看更大范围的对比参考”。也就是在一个问题中,同时包含了两个详细级别的聚合。

比如在最近的航空分析项目中,客户想看:每个机场在各年份的去重旅客数(COUNTD),同时在旁边显示该机场跨年的总去重旅客数。

如果你尝试在 SQL 中这样写:

代码语言:javascript
复制
-- 这在大多数数据库中都会报错
SELECT     
dept_airport,    
EXTRACT(YEAR FROM flight_date) as f_year, 
COUNT(DISTINCT passenger_id) OVER(PARTITION BY dept_airport) as total_distinct
FROM fact_flight_tickets;

你会收到一条冰冷的报错:

代码语言:javascript
复制
DISTINCT is not implemented for window functions

为什么 SQL 关上了这扇门?为什么在 Tableau 中 TOTAL(COUNTD()) 却能轻松实现?这背后隐藏着数据分析技术中最核心的逻辑差异。

一、 SQL 去重汇总:CTE二次聚会

在数据库底层,典型的窗口函数都是关于排序计算,如RANK() OVER() 、ROW_NUMBER、LAG等。也有非典型的二次聚合窗口函数——之所以说不典型,是因为其他的计算也能够完成类似的场景。

而在不典型的窗口计算中,一个特别的案例是涉及到去重的二次聚合。正如开篇所讲,我们要计算不同年月不重合的旅客数量。

可惜的是,大部分数据库都不支持在窗口函数中使用去重计算,这种设定一部分是性能考虑。窗口函数的排序本来就额外占用大量的算力,如果再二次叠加去重的计算,那么窗口计算将更加缓慢。在 Tableau Desktop中,甚至不支持在明细级别的窗口函数。

如何在 SQL 中使用窗口函数完成“去重计数(COUNTD)”呢?处理这种非加性指标(Non-additive)并非窗口函数所擅长,推荐遵循“分层计算”的思维,即动用 CTE (通用表表达式) 或子查询来完成,如下所示:

代码语言:javascript
复制
-- 第一阶段:排除掉不需要的细节,强制降维
-- 这相当于 Tableau 的 EXCLUDE:排除掉具体的客票流水,降维到 (年, 城市, 旅客)
WITH passenger_grain AS (
    SELECT 
        EXTRACT(YEAR FROM flight_date) as f_year,
        dept_airport,
        passenger_id
    FROM fact_flight_tickets
    GROUP BY 1, 2, 3 -- 这里实现了“去重”,生成了一张“旅客-城市-年份”的明细表
)
-- 第二阶段:基于降维后的结果进行窗口计算
SELECT 
    f_year,
    dept_airport,
    -- 此时的 COUNT(passenger_id) 已经是去重后的计数
    COUNT(passenger_id) OVER(PARTITION BY dept_airport) as total_distinct_by_city
FROM passenger_grain;
  1. 第一阶段 (降维/去重):利用 GROUP BY 指定到“人、年、城市”详细级别(LOD,level of detail,Granularity),完成去重计数。
  2. 第二阶段 (开窗/汇总):在已经去重后的结果集上,再用窗口函数进行全局汇总。

这就是 SQL 在面临多个详细级别时的常见处理逻辑:先处理粒度,后处理二次计算。

二、 深度对比:Tableau TOTAL 表计算

Tableau可以使用表计算 TOTAL( COUNTD(Passenger) ) 快速完成上述场景。

SQL窗口函数的“窗口”和Tableau表计算的“表”都是“范围”的意思,既然是范围,就可以设置范围的起点和终点。按照起点和终点能否变化,笔者把窗口函数由易到难分为3类,对应合计、累计汇总和移动汇总3个典型函数。

图9-44 窗口计算的3种特殊类型

很多用户会误以为total和 WINDOW_SUM 是一类,但其实不然。

在我看来,Tableau TOTAL 更像是一个 EXCLUDE LOD 计算,而非普通的窗口函数。它无关次序,结果具有“更高聚合度详细级别”的性质(当然不完全相同)(参见《数据可视化分析第二版》第十章)

  • 窗口函数(如 WINDOW_SUM)是基于视图中已经算好的聚合结果,进行“二次加工”。在对COUNTD(Passenger)二次求和时,不会对用户去重(所以也就不会真得回到 passenger的详细级别)
  • TOTAL 则不同,它会绕过视图当前的细节,回到聚合发生之前,都不同年度的passenger去重计数。相当于排除(Exclude)视图中的指定维度,针对原始明细重新进行一次全局计算。

所以,上述 SQL 中的 CTE 过程,本质上就是在模拟 Tableau 的 EXCLUDE:

  • CTE 里的 GROUP BY 和COUNTD(Passenger),指定。
  • 外层的窗口函数 = TOTAL 的重新聚合过程。

Tableau的表计算和SQL窗口函数是可以相互转换的。

一旦明白了这样的关系,从IT转为业务分析的用户可以快速理解“表计算”的计算过程和SQL的对应关系,而像笔者一样缺乏SQL背景知识的业务分析师,则可以快速理解SQL中最重要的分析函数——窗口函数的应用原理。

三、 进阶:不典型窗口计算 SUM() OVER()

在 SQL 中,还有一种看起来很奇怪的写法:SUM(SUM(Quantity)) OVER(PARTITION BY City)。

两个SUM写法虽同,但本质截然不同。

这就好比美国版的“特朗普”和中国版的“特朗普”虽然音声和手势类似,但只是形式上的某种类似。

SUM(SUM( )) OVER( )是典型的“聚合之上再开窗”,内层的 SUM 和 GROUP BY 相对应,外层的 SUM 和 OVER 相对应,我们常在计算占比(Percent of Total)时用到它。

代码语言:javascript
复制
SELECT     city,    year,    
SUM(quantity) as current_sum,   
 -- 这是不典型的窗口计算:它不包含 
ORDER BY   
SUM(SUM(quantity)) OVER(PARTITION BY city) as total_sum_by_city
FROM orders
GROUP BY city, year;

为什么说它“不典型”?

典型的窗口函数(如 RANK, LAG)依赖 ORDER BY 才能确定“谁是第一”或“谁是前一名”,从而完成排序计算。

排序是最典型的窗口函数,是其他方法难以完成的。

相比之下,SUM(SUM()) 这种写法只关心 Scope(范围)。它是在聚合结果(已经按年、城市分好的块)的基础上,再开一扇窗看透整个城市的所有年份。除了使用这种窗口函数,还可以使用嵌套子查询来更轻松地完成。

不过相比子查询,这种写法在逻辑和语法简洁度上明显更高效的,因为它让数据库在一次查询中同时完成了两个层级的聚合(明细聚合 + 范围汇总)。

可以用一个图示表示这个过程(我在“SQL别裁新解”中的图例):

一旦理解了窗口函数和子查询之间的相关性,我们甚至可以用子查询来完成任何一种窗口函数的计算,并进而理解窗口函数在逻辑上的简洁意义。

四、 结语:致 2026 的技术远航

数据分析的技术工具繁多,但底层逻辑万变不离其宗:维度、度量(指标),以及计算所依赖的详细级别(颗粒度)(在 Power BI 中被称为上下文,但我个人不喜欢这个容易误解的词)。

我计划从 2026 年 启动一个更具雄心的项目——“SQL、Tableau 与 DAX 的系统性逻辑对比”,并最终推出《 SQL 别谈新解》和《 DAX 别裁新解》两本小册子(能否出版则依赖于更多的context)。

当然,广受业内关注的“国产 BI 测评”也会进入第二季,适时也会组织国产 BI 产品经理的座谈会,我们来看一下国产工具最近两三年的进步。

我希望通过这个项目,帮助更多的技术人员跳出“语法”的泥潭,进入“逻辑”的深处。无论你是精通 SQL 的数据库专家,还是擅长 DAX 的 Power BI 达人,亦或是深耕 Tableau 的分析专家,你都会发现,我们虽然用着不同的方言,但在数据逻辑的维度里,我们其实在说同一种思考逻辑。

2026 年,让我们在数据分析的技术逻辑巅峰见!

预祝大家新年快乐!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-02-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Tableau喜乐君 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、 SQL 去重汇总:CTE二次聚会
  • 二、 深度对比:Tableau TOTAL 表计算
  • 三、 进阶:不典型窗口计算 SUM() OVER()
  • 四、 结语:致 2026 的技术远航
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档