在 s-s-rS Report Builder Execute(@Query) 中对列标题使用动态 SQL - 使用来自 1 个表的值作为来自不同表的值的列标题

Posted

技术标签:

【中文标题】在 s-s-rS Report Builder Execute(@Query) 中对列标题使用动态 SQL - 使用来自 1 个表的值作为来自不同表的值的列标题【英文标题】:Using Dynamic SQL for Column Headers in s-s-rS Report Builder Execute(@Query) - Use Values From 1 Table as Col Headers for Values From A Different Table 【发布时间】:2017-12-07 23:57:40 【问题描述】:

我在 SQL Server Reporting Services 2012 上使用 Microsoft SQL Server Report Builder 3.0。

我有一个使用动态 SQL 的存储过程。在 SQL 中执行它时效果很好,但是当我将它用作 Report Builder 中的数据集时,它不会加载任何数据字段。

我将其编写为动态 SQL 的原因是因为我想将特定表中的字段值用作从结果集中不同表访问的其他字段的列标题。

以下是来自 sp 的部分代码。实际的 sp 连接到更多的表并拉取更多的数据字段。

DECLARE @INRM as char(30)
        ,@OUTRM as char(30)
        ,@PROCSTART as char(30)
        ,@PROCEND as char(30)
        ,@Query as NVARCHAR(MAX)

SET NOCOUNT ON;

SELECT ST.SurTimeID, ST.Name
INTO #STL
FROM [livefdb].[dbo].[SurTime_Main] as ST

**SET @INRM = (select c.Name
            from #STL as c
            where c.SurTimeID = 'INRM')
SET @OUTRM = (select c.Name
            from #STL as c
            where c.SurTimeID = 'OUTRM')
SET @PROCSTART = (select c.Name
                from #STL as c
                where c.SurTimeID = 'PROCSTART')
SET @PROCEND = (select c.Name
                from #STL as c
                where c.SurTimeID = 'PROCEND')**

DROP TABLE #STL

-- Insert statements for procedure here
SET @Query = 
'SELECT CAST(CIO.IntraoperativeOperationDateTime as date) as [Operation Date]
    ,REG.AccountNumber as [Account Number]
    ,HRM.Name as [Patient Name]
    ,CSE.OperatingRoom_CwsResRoomID as [Operating Room]
    ,SRG.NameWithCredentialsStored as [Case Surgeon]
    ,ISNULL(CASE    WHEN CONVERT(DATE,INRM.IntraoperativeDateTime) = ''1900-01-01'' THEN ''''
                    ELSE CONVERT(VARCHAR(23),INRM.IntraoperativeDateTime,121)
                    END,'''') as **['+ @INRM +']**
    ,ISNULL(CASE    WHEN CONVERT(DATE,PS.IntraoperativeDateTime) = ''1900-01-01'' THEN ''''
                    ELSE CONVERT(VARCHAR(23),PS.IntraoperativeDateTime,121)
                    END,'''') as **['+ @PROCSTART +']**
    ,ISNULL(CASE    WHEN CONVERT(DATE,PE.IntraoperativeDateTime) = ''1900-01-01'' THEN ''''
                    ELSE CONVERT(VARCHAR(23),PE.IntraoperativeDateTime,121)
                    END,'''') as **['+ @PROCEND +']**
    ,ISNULL(CASE    WHEN CONVERT(DATE,OUTRM.IntraoperativeDateTime) = ''1900-01-01'' THEN ''''
                    ELSE CONVERT(VARCHAR(23),OUTRM.IntraoperativeDateTime,121)
                    END,'''') as **['+ @OUTRM +']**

FROM [livefdb].[dbo].[SurCase_Main] as CSE with (nolock)

INNER JOIN [livefdb].[dbo].[SurCase_Inop] as CIO with (nolock)
on CIO.SourceID = CSE.SourceID
    AND CIO.CwsApptID = CSE.CwsApptID

**LEFT JOIN [livefdb].[dbo].[SurCase_InopTimes] as INRM with (nolock)
on INRM.SourceID = CSE.SourceID
    AND INRM.CwsApptID = CSE.CwsApptID
    AND INRM.IntraoperativeTimeLabel_SurTimeID = ''INRM''**

**LEFT JOIN [livefdb].[dbo].[SurCase_InopTimes] as OUTRM with (nolock)
on OUTRM.SourceID = CSE.SourceID
    AND OUTRM.CwsApptID = CSE.CwsApptID
    AND OUTRM.IntraoperativeTimeLabel_SurTimeID = ''OUTRM''**

**LEFT JOIN [livefdb].[dbo].[SurCase_InopTimes] as PS with (nolock)
on PS.SourceID = CSE.SourceID
    AND PS.CwsApptID = CSE.CwsApptID
    AND PS.IntraoperativeTimeLabel_SurTimeID = ''PROCSTART''**

**LEFT JOIN [livefdb].[dbo].[SurCase_InopTimes] as PE with (nolock)
on PE.SourceID = CSE.SourceID
    AND PE.CwsApptID = CSE.CwsApptID
    AND PE.IntraoperativeTimeLabel_SurTimeID = ''PROCEND''**

LEFT JOIN [livefdb].[dbo].[CwsAppt_Main] as APT with (nolock)
on APT.SourceID = CSE.SourceID
    AND APT.CwsApptID = CSE.CwsApptID

LEFT JOIN [livefdb].[dbo].[RegAcct_Main] as REG with (nolock)
on REG.SourceID = APT.SourceID
    AND REG.VisitID = APT.VisitID

LEFT JOIN [livefdb].[dbo].[HimRec_Main] as HRM with (nolock)
on HRM.SourceID = REG.SourceID
    AND HRM.PatientID = REG.PatientID

LEFT JOIN [livefdb].[dbo].[MisPerson_Names] as SRG with (nolock)
on SRG.SourceID = CSE.SourceID
    AND SRG.UnvUserID = CSE.Surgeon_UnvUserID

WHERE CIO.IntraoperativeOperationDateTime
      BETWEEN ''' + CONVERT(VARCHAR(23),@spFromOperationDate,121) + ''' AND '''
          + CONVERT(VARCHAR(23),@spThruOperationDate,121) + ''''

SurTime_Main 表包含时间类型及其描述...而不是实际时间本身。

SurTime_Main 记录示例:

SurTimeID = 'INRM' (PK) Name = '进入房间'

我想将此表中的描述用作从 SurCase_InopTimes 表中提取的日期/时间的列标题 (SurTime_Main.Name)。 SurCase_InopTimes 表包含输入的实际时间和输入的时间类型。

SurCase_InopTimes 记录示例:

CwsApptID = '1234567890' (PK) IntraoperativeTimeLabel_SurTimeID = 'INRM' (PK)

术中日期时间 = '2000-01-01 00:00:00.000'

CwsApptID = '1234567890' (PK)

术中时间标签_SurTimeID = 'OUTRM' (PK) 术中日期时间 = '2000-01-01 01:00:00.000'

我希望这是有道理的。如果我们的时间类型描述在未来被更新,那么报告将准备好运行更新的列标题描述......至少这是我想要的。

如果动态 SQL 不是用于将数据字段拉入报表生成器的选项,我是否可以在 SQL 或报表生成器本身中完成此操作,以便我的列标题将是来自 SurTime_Main 表的值?

提前谢谢你。

【问题讨论】:

【参考方案1】:

我过去做过类似的事情。

基本上,s-s-rS 总是希望您的数据集在每次执行时返回相同的列。

所以举一个非常简单的例子,而不是返回类似的东西

Creature    Legs    Claws
Dog         4       16
Cat         4       18

然后另一个运行返回类似这样的内容

Creature    Arms    Fingers
Human       2       10
Zombie      2       3

我所做的就是返回这样的东西......

Label    ColumnA    ColumnB     CaptionA    CaptionB
Dog         4       16            Legs        Claws
Cat         4       18            Legs        Claws

下一次使用不同参数的运行可能会返回

Label    ColumnA    ColumnB     CaptionA    CaptionB
Human       2       10            Arms        Fingers
Zombie      2        3            Arms        Fingers

在您的报表设计中,只需将列标题替换为 =First(Fields!CaptionA.Value) 等表达式即可

【讨论】:

谢谢艾伦。在发布之前,我确实知道我可以编写额外的存储过程,并让每个 sp 提取一个特定的时间类型记录以用于列标题,将它们添加为数据集,并用你提到的表达式替换列标题。我不确定是否有更好的方法来实现这一点,但听起来这可能是唯一的方法。感谢您的回复!

以上是关于在 s-s-rS Report Builder Execute(@Query) 中对列标题使用动态 SQL - 使用来自 1 个表的值作为来自不同表的值的列标题的主要内容,如果未能解决你的问题,请参考以下文章

在 s-s-rS Report Builder Execute(@Query) 中对列标题使用动态 SQL - 使用来自 1 个表的值作为来自不同表的值的列标题

将 Reporting Services 2008 配置为使用多个 Report Builder 版本

Report Builder 3.0 - 如何使用大型数据集运行此报告?

如何将此 Crystal Report 公式编写为 s-s-rS 表达式?

将凭据传递给 Sql Report Server 2008

s-s-rS 报告服务器?链接不起作用