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

SSRS:为图表动态重组数据集

在SSRS中重组数据集适配条形图的解决方案

看起来你遇到的是典型的非结构化数据集转结构化宽表的问题,这种情况在SSRS里确实需要一点技巧来处理。下面我会给出两种可行的方案,优先推荐数据源层面的SQL预处理,其次是SSRS内部的表达式处理。

方案一:SQL预处理(最推荐)

如果你的数据源是SQL Server(或支持类似语法的数据库),可以直接在数据集查询里把原始数据转换成你需要的宽格式。假设原始数据存储在一个表RawDrugData中,只有一列Content(存储每行的文本,比如X case 1、100等),步骤如下:

  1. 给所有行分配序号,方便关联描述行和数值行:
    WITH NumberedRows AS (
        SELECT 
            Content,
            ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNum -- 按原始顺序编号
        FROM RawDrugData
    )
    
  2. 拆分描述行(药物+病例)并关联数值行:
    前面9行是药物+病例的描述,后面9行是对应的数值,所以数值行的RowNum减去9就是对应的描述行序号:
    , DrugCasePairs AS (
        SELECT
            -- 拆分出药物名称(第一个空格前的内容)
            LEFT(Content, CHARINDEX(' ', Content) - 1) AS drug,
            -- 拆分出病例名称(第一个空格后的内容)
            RIGHT(Content, LEN(Content) - CHARINDEX(' ', Content)) AS case_name,
            RowNum AS PairRowNum
        FROM NumberedRows
        WHERE RowNum <= 9 -- 前9行是描述行
    ),
    ValuesRows AS (
        SELECT
            CAST(Content AS INT) AS usage_value,
            RowNum - 9 AS PairRowNum -- 对应描述行的序号
        FROM NumberedRows
        WHERE RowNum > 9 -- 后9行是数值行
    )
    
  3. 关联后转成宽表(Pivot):
    SELECT
        drug,
        [case 1], [case 2], [case 3]
    FROM (
        SELECT d.drug, d.case_name, v.usage_value
        FROM DrugCasePairs d
        JOIN ValuesRows v ON d.PairRowNum = v.PairRowNum
    ) AS SourceData
    PIVOT (
        SUM(usage_value)
        FOR case_name IN ([case 1], [case 2], [case 3])
    ) AS PivotTable;
    
    执行这个查询后,就能直接得到你需要的宽格式数据集,直接用来做条形图就可以了。

方案二:SSRS内部表达式处理(无需修改数据源)

如果无法修改数据源查询,可以在SSRS里通过自定义代码和Lookup函数来重组数据:

  1. 先确保数据集包含行号:
    在数据集查询里添加行号(如果是SQL数据源,用ROW_NUMBER();如果是其他数据源,比如CSV,可以在SSRS数据集属性里添加计算字段RowNum,表达式为=RowNumber("YourDataSetName"))。

  2. 创建自定义代码:
    在报表的「报表属性」→「代码」里添加以下VB代码,用来存储药物-病例的映射关系:

    Dim drugCaseMap As New Dictionary(Of Integer, String())
    
    Public Sub AddDrugCase(rowNum As Integer, drug As String, caseName As String)
        drugCaseMap(rowNum) = New String() {drug, caseName}
    End Sub
    
    Public Function GetDrug(rowNum As Integer) As String
        If drugCaseMap.ContainsKey(rowNum) Then
            Return drugCaseMap(rowNum)(0)
        Else
            Return ""
        End If
    End Function
    
    Public Function GetCase(rowNum As Integer) As String
        If drugCaseMap.ContainsKey(rowNum) Then
            Return drugCaseMap(rowNum)(1)
        Else
            Return ""
        End If
    End Function
    
  3. 在报表里添加隐藏的Tablix来初始化映射:
    添加一个Tablix,数据源选你的原始数据集,设置为隐藏(在Tablix属性→可见性里选「隐藏」)。在Tablix的细节行里,添加两个文本框,分别设置表达式:

    • 第一个文本框(绑定行号≤9的行):=Code.AddDrugCase(Fields!RowNum.Value, Split(Fields!Content.Value, " ")(0), Split(Fields!Content.Value, " ")(1))
    • 第二个文本框(绑定行号>9的行):不需要设置,只是用来触发行的执行
  4. 创建计算字段关联数值和药物病例:
    在数据集里添加三个计算字段:

    • drug:表达式为=Code.GetDrug(Fields!RowNum.Value - 9)
    • case_name:表达式为=Code.GetCase(Fields!RowNum.Value - 9)
    • usage_value:表达式为=IIF(Fields!RowNum.Value >9, CInt(Fields!Content.Value), 0)
  5. 用重组后的数据集做条形图:
    创建条形图,设置类别组为drug,系列组为case_name,值为usage_value,就能得到你需要的图表了。

额外提示

  • 如果你的原始数据顺序绝对固定(药物病例行严格在前,数值行严格对应),方案一的SQL方法是最稳定高效的;
  • 方案二适合数据源无法修改的场景,但要注意报表的性能,尤其是数据量大的时候;
  • 条形图的设置:把类别轴设为药物名称,系列设为病例,值为使用量,就能直观展示各类药物在不同病例中的使用情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:23:03