Question

I need to add the column of REGION to a SSRS report that relies on a stored procedure for population. Within the stored procedure, it uses a pivot table. I know the relation lives in a separate table so I think it's a matter of putting the JOIN in the right place, but am I on the right track? I noted where I think it should go in the comments in the below code:

USE [TEST]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[abc_sp_ACE_GetFormDataNoContactID]
@FormObjectKey varchar(100)
as
DECLARE @SEQN varchar(5)

--CREATE TEMP TABLE
CREATE table #tmpFormData
(ID varchar(10) NOT NULL
)

DECLARE @ItemName varchar(50), @TableName varchar(50), @SQL varchar(max), @vary varchar(1000), @final varchar(max)
DECLARE @ItemList varchar(max),@ItemListUnPivot varchar(max),@DataType varchar(20),@Prompt varchar(500)
SET @ItemList = ''
SET @ItemListunPivot = ''

DECLARE contact_cursor CURSOR FOR
select ItemName,TableName,Prompt
from abc_ACE_Form Form
    join abc_ACE_FormItem FormItem 
        on Form.objectkey = FormItem.formkey
where Form.objectKey = @FormObjectKey
and FormItem.isVisible = 1 and itemtype not in ('ContentBlock','Divider')
order by PositionNumber

OPEN contact_cursor

FETCH NEXT FROM contact_cursor
INTO @ItemName, @TableName, @Prompt

-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
WHILE @@FETCH_STATUS = 0
BEGIN
    --Get DATA TYPE
    SELECT @DataType = 
        CASE t.name 
            WHEN 'varchar' THEN 'varchar(' + Convert(varchar(10),c.max_length) + ')'
            WHEN 'float' THEN 'varchar(200)'
            ELSE t.name
        END
        FROM sys.objects a
            JOIN sys.columns AS c
                on c.object_id = a.object_ID
        JOIN sys.types AS t ON c.user_type_id=t.user_type_id
        WHERE c.name = @ItemName
        and a.Name = @TableName


    SELECT @SQL = 'ALTER TABLE #tmpFormData' 
    select @vary = ' ADD ' + @ItemName + ' ' + @DataType
    select @final = @sql + @vary
    Exec ( @final)

    If len(@ItemList) = 0
        BEGIN
            Select @ItemList = @ItemList + @ItemName
        END
    ELSE
        BEGIN
            Select @ItemList = @ItemList + ',' + @ItemName 
        END

    if len(@ItemListUnPivot) = 0
        BEGIN
            Select @ItemListUnPivot = 'convert(varchar(100),' + @ItemName + ') as ' + @ItemName 
        END
    ELSE
        BEGIN
            Select @ItemListUnPivot = @ItemListUnPivot + ',' + 'convert(varchar(100),' + @ItemName + ') as ' + @ItemName
        END


   -- This is executed as long as the previous fetch succeeds.
   FETCH NEXT FROM contact_cursor
   INTO @ItemName, @TableName, @Prompt
END

CLOSE contact_cursor
DEALLOCATE contact_cursor

SET @SQL = ''

SELECT @SQL = 'INSERT INTO #tmpFormData (ID,' + @ItemList + ')'
Select @SQL = @SQL + ' select ID, ' + @ItemList + ' from ' + @Tablename 
SELECT @SQL = @SQL + ' join abc_ACE_formtrans on convert(varchar(128),trankey) = workflowtran_key where formkey = ''' + @FormObjectKey + ''''
EXEC(@SQL)

SELECT @SQL = 'SELECT ID, measure, value, '''' as ChapterName, '''' as FormTitle, region  
    FROM( select ID, ' + @ItemListUnPivot + ' from #tmpFormData) p UNPIVOT( VALUE FOR measure IN (' + @ItemList + ')) AS unpvt'
    -- ADDED 'region' HERE...I think this is where the JOIN to the table 'REG' should go

CREATE TABLE #tmp (ID int, measure varchar(500), value varchar(500), ChapterName varchar(80), FormTitle varchar(255), region varchar(4))
INSERT INTO  #tmp (ID, measure, value, ChapterName, FormTitle, region)
        --ADDED REGION TO BOTH CREATE AND INSERT STATEMENTS


EXEC (@SQL)

update #tmp
set measure = Prompt
    , ChapterName = nm.Company
    , FormTitle = Form.Title
from abc_ACE_Form Form
    join abc_ACE_FormItem FormItem 
        on Form.objectkey = FormItem.formkey
    join #tmp a
        on FormItem.ItemName = measure
    left join Name nm 
        on nm.ID = a.ID
where Form.objectKey = @FormObjectKey
and FormItem.isVisible = 1

SELECT * from #tmp order by ChapterName, ID

drop table #tmp
drop table #tmpFormData

Can it even be done? Do I need to rewrite the SP(please say no)?

UPDATE: It was mentioned that I could write the results of the SP to a temporary table and then join the temporary table to the table that has the additional column. A great answer, but I can't seem to find where in the process to add the join. My first guess, after 2 hours of trial and error is to add it before the #tmp file is created, yes?

UPDATE2: Okay, I added the JOIN at the last SELECT statement (SELECT * FROM #tmp), changing the * to all columns from #tmp and adding the region column. I trip over to SSRS and can see the column populate(yay!), but then I flip over to preview the report and it blows away some 30 columns(boo!). It's like the change blows the pivot table up, but the pivot/unpivot should have already taken place within the procedure, why would it do this?

Was it helpful?

Solution 2

While @Mike-Honey 's answer helped point me to how to add the column in the SSRS report, I ultimately decided to alter the SP as it was decided the region data would be necessary for future reports. I coded the last SELECT statement like so:

SELECT 
A.ID -- EXPANDED FROM * IN ORDER TO INCLUDE ADDITIONAL COLUMN 
, A.measure
, A.value
, A.ChapterName
, A.FormTitle
, DC.CH_COL_REGION -- ADDED 
from #tmp A
    JOIN DEMO_CHAPTER DC -- ADDED 
    ON A.ID = DC.ID -- ADDED 
order by A.ChapterName, A.ID

OTHER TIPS

I would not attempt to dynamically pivot data in SQL - as you are finding this is very complex and any change can break downstream processes.

SSRS can perform this task using Column Groups.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top