You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SSRS中跨多个不同数据集实现CountDistinct去重计数的方法

SSRS 跨数据集同维度去重计数实现方案

本方案无需修改原有数据集的长查询逻辑,支持后续快速扩展多数据集统计,避免多查询UNION/关联带来的SQL冗余问题。


方案一:全局字典缓存方案(推荐,扩展性最优)

适合后续需要新增3个及以上产品组统计的场景,新增数据集时仅需加1行表达式即可完成适配。

  • 添加报表自定义代码
    打开报表右键选择「报表属性」-「代码」,粘贴以下VB代码:
    ' 按销售人员编码存储去重后的客户编码集合
    Private customerMap As New System.Collections.Generic.Dictionary(Of String, System.Collections.Generic.HashSet(Of String))
    
    ' 向指定销售人员的客户集合中批量添加客户,返回当前集合总数
    Public Function LoadCustomer(salesPersonCode As String, customerList As Object()) As Integer
        If Not customerMap.ContainsKey(salesPersonCode) Then
            customerMap.Add(salesPersonCode, New System.Collections.Generic.HashSet(Of String))
        End If
        For Each custCode As Object In customerList
            If Not IsDBNull(custCode) Then
                customerMap(salesPersonCode).Add(custCode.ToString().Trim())
            End If
        Next
        Return customerMap(salesPersonCode).Count
    End Function
    
    ' 获取指定销售人员的去重客户总数
    Public Function GetTotalDistinctCount(salesPersonCode As String) As Integer
        If customerMap.ContainsKey(salesPersonCode) Then
            Return customerMap(salesPersonCode).Count
        End If
        Return 0
    End Function
    
    ' 渲染前清空缓存,避免多次加载导致计数累加
    Public Sub ClearCache()
        customerMap.Clear()
    End Sub
    
  • 配置Tablix基础数据源
    单独新建一个轻量数据集,查询所有需要统计的销售人员编码、名称列表(仅需从维度表取数,或对现有两个数据集的销售人员做UNION去重即可,逻辑量极小),将该数据集作为Tablix的绑定数据源,避免两个数据集人员不一致导致漏统计。
  • 配置加载逻辑与计数单元格
    • 在Tablix中新增一个隐藏列(列可见性设为隐藏),在该列的明细行单元格写入以下表达式,加载两个数据集的客户数据:
      =Code.LoadCustomer(Fields!SalesPerson_Code.Value, LookupSet(Fields!SalesPerson_Code.Value, Fields!SalesPerson_Code.Value, Fields!Customer_Code.Value, "D1"))
      =Code.LoadCustomer(Fields!SalesPerson_Code.Value, LookupSet(Fields!SalesPerson_Code.Value, Fields!SalesPerson_Code.Value, Fields!Customer_Code.Value, "D2"))
      
      后续新增D3、D4等其他产品组数据集时,仅需在该位置新增一行对应数据集的LoadCustomer调用即可,无需修改其他逻辑。
    • 在需要展示count_Customer_XY的单元格写入以下表达式,直接取去重后的总数:
      =Code.GetTotalDistinctCount(Fields!SalesPerson_Code.Value)
      
  • 配置缓存重置
    在报表页眉新增一个隐藏文本框,文本框值设为=Code.ClearCache(),保证每次报表渲染前先清空历史缓存,避免翻页、参数刷新时计数累加错误。

方案二:单函数合并方案(适合固定2个数据集的场景)

如果后续不需要扩展更多数据集,可以用更简化的写法,无需全局缓存:

  • 在报表自定义代码中粘贴以下函数:
    Public Function CountTwoSetDistinct(arr1 As Object(), arr2 As Object()) As Integer
        Dim hs As New System.Collections.Generic.HashSet(Of String)
        For Each c In arr1
            If Not IsDBNull(c) Then hs.Add(c.ToString().Trim())
        Next
        For Each c In arr2
            If Not IsDBNull(c) Then hs.Add(c.ToString().Trim())
        Next
        Return hs.Count
    End Function
    
  • Tablix直接绑定任意一个数据集的销售人员维度,计数单元格直接写入以下表达式即可:
    =Code.CountTwoSetDistinct(
    LookupSet(Fields!SalesPerson_Code.Value, Fields!SalesPerson_Code.Value, Fields!Customer_Code.Value, "D1"),
    LookupSet(Fields!SalesPerson_Code.Value, Fields!SalesPerson_Code.Value, Fields!Customer_Code.Value, "D2")
    )
    

注意事项

  • 关联匹配必须使用SalesPerson_Code、Customer_Code这类唯一编码字段,禁止用名称字段匹配,避免重名导致统计错误
  • 单报表客户总数据量在10万行以内时,上述方案性能无明显问题;如果数据量更大,建议在数据层用CTE封装公共查询逻辑,避免SSRS前端计算卡顿
  • SSRS原生聚合函数(如CountDistinct、Sum)不支持跨数据集作用域,直接调用会返回作用域错误,不要尝试用原生函数嵌套实现该需求

内容的提问来源于stack exchange,提问作者Yann Kerboul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 04:24:13