Search code examples
sqlcasetable-valued-parameters

SQL Performance issue when using CASE


I have a SP that returns quite a lot of data every second and is shown in a grid. I'm now trying to reduce bandwidth and thinking of returning only columns currently shown in my grid.

This is of course simplified and minimized but basically what I had was the following SP:

SELECT
[Animals].[AnimalID] AS [AnimalID],
[Animals].[name] AS [AnimalName],
[Foods].[DisplayName] AS [Food],
[Animals].[Age] AS [AnimalAge],
[Animals].[AmountOfFood] AS [AmountOfFood]

What I’m currently trying is to pass a TVP of the names of the fields (@fields) currently shown on the grid and returning only required fields as such:

SELECT
[Animals].[AnimalID] AS [AnimalID],
[Animals].[name] AS [AnimalName],
CASE 
    WHEN ('Food' in (select * from @fields)) 
    THEN [Foods].[DisplayName] 
END AS [Food],
CASE 
    WHEN ('AnimalAge' in (select * from @fields)) 
    THEN [Animals].[Age] 
END AS [AnimalAge],
CASE 
    WHEN ('AmountOfFood' in (select * from @fields)) 
    THEN [Animals].[AmountOfFood] 
END AS [AmountOfFood]

The problem I'm facing is that (as could be expected) my SP went from taking ~200 ms to taking ~1 sec

Is there any way to maybe rewrite this so that it doesn’t kill us?

My kingdom for a foreach!!!


Solution

  • In SQL Server, you can also do this with dynamic SQL. Something like:

    declare @sql nvarchar(max);
    
    select @sql = (select ', '+
                          (case when FieldName = 'Food' then 'Foods.DisplayName'
                                when FieldName = 'AnimalAge' then 'Animals.Age'
                             . . .
                           end)
                   from @fields
                   for xml path ('')
                  );
    
    select @sql = 'select [Animals].[AnimalID] AS [AnimalID], [Animals].[name] AS [AnimalName]'+@sql+RESTOFQUERY;
    
    exec(@sql);