sqlsql-serverpivotunion

Receiving extra rows in the result set


I have 2 tables in SQL Server, an ItemTable and a PropertyTable.

They are defined as follows:

ItemTable:

ItemName ItemIsEnabled ObjectName
Rule01 1 Object01
Rule02 1 Object01
Rule03 1 Object03

PropertyTable:

PropertyName PropertyIsEnabled ObjectName
Prop01 1 Object01
Prop02 1 Object02

There could be rows in ItemTable for an ObjectName that doesn't exist in the PropertyTable and vice versa.

I wrote a stored procedure that returns a pivoted result set based on the ObjectName passed in. For example, with 'Object01' passed in as parameter, the stored procedure should return something like this:

ObjectName Rule01 Rule02 Prop01
Object01 1 1 1

But, I am getting rows for Object02 and Object03.

How do I get just the pivoted columns for passed in parameter. I think there is a where clause missing in my code.

Stored procedure code:

DECLARE @cols AS NVARCHAR(MAX) = '';    
DECLARE @cols1 AS NVARCHAR(MAX) = '';   
DECLARE @query AS NVARCHAR(MAX) = '';

SELECT @cols = @cols + QUOTENAME(ItemName) + ',' 
FROM 
    (SELECT DISTINCT ItemName 
     FROM ItemTable 
     WHERE LOWER(ObjectName) = LOWER('Object01')  
     GROUP BY ItemName) AS tmp

SELECT @cols = SUBSTRING(@cols, 0, LEN(@cols))

SELECT @cols1 = @cols1 + QUOTENAME(PropertyName) + ',' 
FROM 
    (SELECT DISTINCT PropertyName 
     FROM PropertyTable 
     WHERE LOWER(ObjectName) = LOWER('Object01') 
     GROUP BY PropertyName) AS tmp1

SELECT @cols1 = SUBSTRING(@cols1, 0, LEN(@cols1))

SET @query = '
SELECT * FROM 
(    
    SELECT  
        I.ItemName AS [Name]        
        ,V.ValueColumn 
        ,I.ObjectName AS [ObjectName]
    FROM ItemTable I
--tried adding a where clause here; isn't working
    
    CROSS APPLY (
        SELECT 
            CAST(I.IsEnabled AS VARCHAR(50)) AS [ValueColumn]
    ) V

    UNION
    SELECT 
        P.PropertyName as [Name]
        ,V1.ValueColumn 
        ,P.ObjectName AS [ObjectName]
    FROM PropertyItem P
--tried adding a where clause here; isn't working   
    CROSS APPLY (
    SELECT          
            P.PropertyIsEnabled AS [ValueColumn]
    ) V1    
) src
PIVOT
(
    max(ValueColumn) for [Name] in (' + @cols + ', ' +  @cols1 + ')
) piv'

Solution

  • See example

    ItemName ItemIsEnabled ObjectName
    Rule01 1 Object01
    Rule02 1 Object01
    Rule03 1 Object03
    Rule04 1 Object05
    PropertyName PropertyIsEnabled ObjectName
    Prop01 1 Object01
    Prop02 1 Object02
    Prop02 1 Object04
    DECLARE @cols AS NVARCHAR(MAX) = '';
    DECLARE @query AS NVARCHAR(MAX) = '';
    DECLARE @SelObjName AS NVARCHAR(100) = 'Object01';
    
    select @cols=string_agg(ItemName,',')
    from(
    select ObjectName,ItemName,ItemisEnabled
    from ItemTable
    where ObjectName=@selObjName
    union 
    select ObjectName,PropertyName,PropertyIsEnabled
    from PropertyTable
    where ObjectName=@selObjName
    )t;
    set @cols=coalesce(@cols,'noObject' );
    
    set  @query='
    select @ObjName as ObjectName,'+@cols+'
     from(select ObjectName,ItemName,ItemIsEnabled
         from ItemTable
         where ObjectName=@ObjName
         union all
         select ObjectName,PropertyName,PropertyIsEnabled
         from PropertyTable
         where ObjectName=@ObjName 
      )src1
    Pivot (
       max(ItemIsEnabled) for Itemname in('+@cols+' )
    )pvt1 '
    ;
    execute sp_executeSQL @query, N'@ObjName varchar(30)',@ObjName=@SelObjName;
    
    ObjectName Prop01 Rule01 Rule02
    Object01 1 1 1

    fiddle