Click here to monitor SSC
SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
 
 
 
        
Home       Members    Calendar    Who's On


Add to briefcase 12»»

Dynamic Filter and Order By Expand / Collapse
Author
Message
Posted Monday, October 1, 2012 5:16 AM


Mr or Mrs. 500

Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500

Group: General Forum Members
Last Login: Thursday, June 12, 2014 9:30 AM
Points: 513, Visits: 1,129
Hi,

I'm doing some testing with dynamic filtering and order by clause.
I'm comparing dynamic SQL vs using the CASE statement...
DECLARE @FilterName NVARCHAR(100) = 'M%'
DECLARE @FilterSalary FLOAT = 3000
DECLARE @OrderField INT = 0 --0 empname, 1 salary, 2 - empid
DECLARE @Query NVARCHAR(500)
DECLARE @Params NVARCHAR(500)

SET @Query = 'SELECT empid, empname, salary FROM dbo.Employees WHERE 1 = 1'
SET @Params = '@FilterNameIn NVARCHAR(100), @FilterSalaryIn FLOAT'

IF LEN(@FilterName) > 0
SET @Query = @Query + ' AND empname LIKE @FilterNameIn'
IF LEN(@FilterSalary) > 0
SET @Query = @Query + ' AND salary > @FilterSalaryIn'
IF @OrderField = 0
SET @Query = @Query + ' ORDER BY empname'
IF @OrderField = 1
SET @Query = @Query + ' ORDER BY salary'
IF @OrderField = 2
SET @Query = @Query + ' ORDER BY empid'

EXEC sp_executesql @query, @Params, @FilterNameIn = @FilterName, @FilterSalaryIn = @FilterSalary

SELECT empid, empname, salary FROM dbo.Employees WHERE
empname LIKE CASE WHEN LEN(@FilterName) > 0 THEN @FilterName ELSE empname END
AND
salary >= ISNULL(@FilterSalary, 0)
ORDER BY
CASE WHEN @OrderField = 0 THEN empname END,
CASE WHEN @OrderField = 1 THEN salary END,
CASE WHEN @OrderField = 2 THEN empid END

Initially I tried
ORDER BY 
CASE
WHEN @OrderField = 0 THEN empname
WHEN @OrderField = 1 THEN salary
WHEN @OrderField = 2 THEN empid
END

To order by only one column but since the fields have different data types SQL gave an error. I could do a CAST but salary as NVARCHAR doesn't give good results... So I used the 3 columns sort.....
In both cases the execution plan is very similar, the CASE statement has a Compute Scalar with 0% (from the CASE statement)...
But if I order by the 3rd column ( = 2) to non dynamic statement, according to execution plan comparing both, is much "heavier" since it orders by 2 NULL columns and only then by the desired column....
Is this a case where Dynamic SQL can be used, where it's better than "regular" SQL statements?

Thanks,
Pedro




If you need to work better, try working less...
Post #1366489
Posted Tuesday, October 2, 2012 8:39 AM


SSChampion

SSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampion

Group: General Forum Members
Last Login: Today @ 1:23 PM
Points: 13,279, Visits: 12,113
You should read this article from Gail about catch all queries. http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/

_______________________________________________________________

Need help? Help us help you.

Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

Need to split a string? Try Jeff Moden's splitter.

Cross Tabs and Pivots, Part 1 – Converting Rows to Columns
Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs
Understanding and Using APPLY (Part 1)
Understanding and Using APPLY (Part 2)
Post #1367079
Posted Tuesday, October 2, 2012 9:00 AM


Mr or Mrs. 500

Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500

Group: General Forum Members
Last Login: Thursday, June 12, 2014 9:30 AM
Points: 513, Visits: 1,129
Sean Lange (10/2/2012)
You should read this article from Gail about catch all queries. http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/

Thanks, I've read it and it answers my question...
But is there a way of having a dynamic ORDER BY with CASE clause without having N order columns?!
ORDER BY CASE WHEN @ordfld = 1 THEN MoneyField WHEN @ordfld = 2 THEN NameField END

this raises an error.. it has to be written
ORDER BY CASE WHEN @ordfld = 1 THEN MoneyField END, CASE WHEN @ordfld = 2 THEN NameField END

which makes 3 order by clauses when I only want one, even if they can be NULL...

Thanks,
Pedro




If you need to work better, try working less...
Post #1367101
Posted Tuesday, October 2, 2012 9:36 AM
Mr or Mrs. 500

Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500

Group: General Forum Members
Last Login: Today @ 7:42 AM
Points: 575, Visits: 3,391
if you know where the column that you want to Order By, sits, you can do

select
col1
,col2
,col3
from tablename
order by 1

this will order by the first column.
change it to 'order by 2' to order by the second column
Post #1367125
Posted Tuesday, October 2, 2012 9:51 AM


Mr or Mrs. 500

Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500

Group: General Forum Members
Last Login: Thursday, June 12, 2014 9:30 AM
Points: 513, Visits: 1,129
Thanks... using the column number isn't as much readable friendly as is the column name.... but it works fine
Is there any problem using the column number besides risking adding a column to the query and messing the order and not being so friendly?!

Thanks,
Pedro




If you need to work better, try working less...
Post #1367135
Posted Tuesday, October 2, 2012 10:59 AM


SSChampion

SSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampion

Group: General Forum Members
Last Login: Today @ 1:23 PM
Points: 13,279, Visits: 12,113
PiMané (10/2/2012)
Thanks... using the column number isn't as much readable friendly as is the column name.... but it works fine
Is there any problem using the column number besides risking adding a column to the query and messing the order and not being so friendly?!

Thanks,
Pedro


It will work but referring to columns by ordinal position is fraught with maintenance issues. You have already defined the problem. The query changes and the person making the change doesn't know or even think about the order by variable stuff going on.


_______________________________________________________________

Need help? Help us help you.

Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

Need to split a string? Try Jeff Moden's splitter.

Cross Tabs and Pivots, Part 1 – Converting Rows to Columns
Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs
Understanding and Using APPLY (Part 1)
Understanding and Using APPLY (Part 2)
Post #1367182
Posted Tuesday, October 2, 2012 12:47 PM


Mr or Mrs. 500

Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500

Group: General Forum Members
Last Login: Thursday, June 12, 2014 9:30 AM
Points: 513, Visits: 1,129
Thanks to all for the help..
Pedro




If you need to work better, try working less...
Post #1367238
Posted Wednesday, October 3, 2012 8:17 AM


Mr or Mrs. 500

Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500

Group: General Forum Members
Last Login: Thursday, June 12, 2014 9:30 AM
Points: 513, Visits: 1,129
Hi,

I just made a simple test... I build a dynamic SQL to execute and executed the same query directly in SMSS...
Can anyone explain why the dynamic SQL is 46% of total time and the same query but "fixed" is 54%, as shown in the attachment..?!?!

CREATE NONCLUSTERED INDEX [idx_Employees_003] ON [dbo].[Employees] 
(
[empname] ASC,
[salary] ASC
);

This is the index being used...

If I use the "fixed" SQL but "guessing" the parameters, like this:
SELECT empid, empname, salary FROM dbo.Employees WHERE empname >= CASE WHEN LEN(@FilterName) > 0 THEN @FilterName ELSE empname END AND salary >= ISNULL(@FilterSalary, 0)

SQL suggests an index on salary including empid and empname..

If instead of empname >= ... I use empname LIKE ..., on the dynamic SQL, it also suggests the index on salary and include empid and empname... Isn't LIKE as good as >= for index seeks?!?

Thanks,
Pedro




If you need to work better, try working less...


  Post Attachments 
execution_plan.jpg (1 view, 152.82 KB)
Post #1367712
Posted Wednesday, October 3, 2012 8:40 AM


SSChampion

SSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampionSSChampion

Group: General Forum Members
Last Login: Today @ 1:23 PM
Points: 13,279, Visits: 12,113

... Isn't LIKE as good as >= for index seeks?!?


NO LIKE is not SARGable so you will get scans. It has to examine every row to determine if it is a match or not.


_______________________________________________________________

Need help? Help us help you.

Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

Need to split a string? Try Jeff Moden's splitter.

Cross Tabs and Pivots, Part 1 – Converting Rows to Columns
Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs
Understanding and Using APPLY (Part 1)
Understanding and Using APPLY (Part 2)
Post #1367733
Posted Wednesday, October 3, 2012 8:55 AM


Mr or Mrs. 500

Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500Mr or Mrs. 500

Group: General Forum Members
Last Login: Thursday, June 12, 2014 9:30 AM
Points: 513, Visits: 1,129
Sean Lange (10/3/2012)
NO LIKE is not SARGable so you will get scans. It has to examine every row to determine if it is a match or not.


So a LIKE 'M%' is better replaced with a >= 'M' AND < 'N'..




If you need to work better, try working less...
Post #1367749
« Prev Topic | Next Topic »

Add to briefcase 12»»

Permissions Expand / Collapse