如何在SSRS Report Builder中汇总相同测试状态的连续序列号
需求背景
- 现有一批带唯一序列号的送测部件,所有序列号均归属于和车间订单号(shop order number)绑定的容器(container)
- 此前相关数据全部采用纸质手动记录追踪,现在计划通过SSRS Report Builder按车间订单生成报表,展示每个容器及其关联的所有序列号信息
- 当前已实现按容器编号分组,展示单条序列号、测试通过/失败状态、序列号计数的功能,但生成的报表长达数十页,可读性差
优化需求
- 相同测试状态的连续序列号合并展示在同一行,仅标注该区间的首个和最后一个序列号
- 不同状态的连续序列号区间单独分行展示
- 保留展示对应容器内的序列号总数量
实现方案
推荐优先在SQL查询层完成数据聚合,性能更好也更稳定;如果没有权限修改查询逻辑,也可以在SSRS报表层面通过自定义代码实现。
方案1:SQL层处理(经典「间隙与孤岛」问题解法)
你遇到的是典型的连续序列分组问题,业内也称孤岛问题。假设你的原始数据表包含容器ID、序列号、测试状态、车间订单号字段,且序列号为可排序的数值/可提取数值的字符串,参考查询逻辑如下:
WITH 排序预处理 AS ( SELECT 容器ID, 序列号, 测试状态, -- 按容器、测试状态分组后,对序列号升序排序 ROW_NUMBER() OVER (PARTITION BY 容器ID, 测试状态 ORDER BY 序列号) AS 排序序号 FROM 你的原始业务表 WHERE 车间订单号 = @ShopOrderNum -- 直接使用SSRS的车间订单参数即可 ), 连续区间分组 AS ( SELECT 容器ID, 序列号, 测试状态, -- 连续的序列号减去排序序号的差值是固定值,用这个值作为连续区间的分组标识 CAST(序列号 AS INT) - 排序序号 AS 区间分组ID -- 如果序列号带前缀,比如是SN00012格式,就先提取数值部分:CAST(RIGHT(序列号, 5) AS INT) - 排序序号 AS 区间分组ID FROM 排序预处理 ) SELECT 容器ID, MIN(序列号) AS 区间起始序列号, MAX(序列号) AS 区间结束序列号, 测试状态, COUNT(序列号) AS 本区间序列号数量, -- 窗口函数统计同一容器的总序列号数 SUM(COUNT(序列号)) OVER (PARTITION BY 容器ID) AS 容器内总序列号数 FROM 连续区间分组 GROUP BY 容器ID, 测试状态, 区间分组ID ORDER BY 容器ID, MIN(序列号)
查询返回的结果就是你需要的预期结构,直接绑定到SSRS的表格控件即可,不需要额外做复杂分组配置。
方案2:SSRS报表层处理
如果无法修改查询SQL,可以通过SSRS自定义代码实现分组:
- 右键报表空白处打开【报表属性】,切换到【代码】标签,粘贴如下VB自定义代码:
Dim 上一个序列号 As Integer = 0 Dim 上一个状态 As String = "" Dim 分组ID As Integer = 0 ' 获取连续区间分组标识 Function 获取分组ID(当前序列号 As Integer, 当前状态 As String) As Integer If 当前序列号 = 上一个序列号 + 1 And 当前状态 = 上一个状态 Then Return 分组ID Else 分组ID +=1 上一个序列号 = 当前序列号 上一个状态 = 当前状态 Return 分组ID End If End Function - 给表格设置两级分组:
- 父分组按
容器ID分组,用于区分不同容器 - 子分组的分组表达式写:
=Code.获取分组ID(CInt(Fields!序列号.Value), Fields!测试状态.Value)
- 父分组按
- 在子分组的行单元格中配置展示值:
- 区间首尾序列号分别写
=Min(Fields!序列号.Value)和=Max(Fields!序列号.Value) - 本区间数量:
=Count(Fields!序列号.Value, "你的子分组名称") - 容器总数量:
=Count(Fields!序列号.Value, "你的父分组名称")
- 区间首尾序列号分别写
内容的提问来源于stack exchange,提问作者David Lopez
相关产品推荐
相关产品推荐

