软件设计师窗口函数容易混淆的地方,是把“按组计算”都看成“每组只留一行”。先问结果要保留每条明细,还是只要每组汇总,比先背函数名更有用。知英教育建议在算数前,先写下预期保留哪些记录。

四条练习记录,两种展示要求

自编表practice_log有四行,列为记录号、小组、练习分钟数:1号甲组12分钟,2号甲组18分钟,3号乙组7分钟,4号乙组13分钟。甲组合计30,乙组合计20。

若只想列出每组总分钟数,用小组GROUP BY后得到甲、乙两行。这里聚合查询行数由分组决定,不是原表四行逐条保留。若想在每条记录旁边显示组内合计,则需要另一种结果形状。

四条自编练习记录经过GROUP BY得到两行汇总,使用窗口求和保留四行
先确定要汇总行还是明细行,再选择计算写法。
SELECT log_id, team, minutes,
       SUM(minutes) OVER
         (PARTITION BY team) AS team_total
FROM practice_log;

这段窗口分区聚合给甲组两条记录各附上30,给乙组两条各附上20,结果仍是四行。PARTITION BY划定每条记录参与计算的同组范围;OVER使这里的SUM按窗口方式使用,并没有把同组明细合并掉。

分区相同,不代表行数处理相同

学习软件设计师窗口函数时,可把每行想成一张卡片,组内总数是写在卡片旁的附加值。窗口分区聚合关心计算可见的同组记录,GROUP BY则可能先把记录压成汇总结果。不要把PARTITION BY当成GROUP BY的另一个拼写。

检查聚合查询行数时,还要看完整查询是否另有筛选、分组或去重。窗口计算本身不合并输入行,并不表示任意含窗口函数的复杂查询都会与原始表行数相同。

先筛选分钟数再做窗口求和,乙组只剩13分钟记录,组内合计变为13
窗口看到的是前序条件处理后的记录,不会把已筛掉的行重新算入。

WHERE先筛掉的记录,不再参与本层窗口计算

若上面的查询增加WHERE minutes >= 10,7分钟那行先被筛掉,剩三行。甲组窗口合计仍为30,乙组合计变为13。若要按窗口算出的结果继续筛选,可先在子查询中计算,再由外层查询筛选。

知英教育建议用“先剩几行、再按什么分区”两步验算。这里窗口分区聚合处理的是筛选后的三条记录,不能把原先乙组20分钟的合计直接搬过来。

不加窗口排序时按全分区求和,加排序后需另核对窗口框架
窗口内排序会影响默认框架,不能直接当成最终展示顺序。

加了ORDER BY,还要检查窗口框架

本例OVER内没有ORDER BY,默认框架覆盖整个分区。加入排序后,默认框架可能按排序推进,并包含与当前排序值相同的同行,结果未必仍是每行固定的组总数。窗口内排序也不保证最终输出顺序。

复习软件设计师窗口函数,可先核对输入行,再判断分区和框架,最后检查聚合查询行数。需要安排后续学习,可查看软件设计师备考,向知英教育说明是行数、分区还是筛选顺序没有想清楚。