Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 alter sort order without using dynamic sql

Author  Topic 

nic
Posting Yak Master

209 Posts

Posted - 2003-03-07 : 13:27:20
Hi I have a sproc where I need to be able to alter the sort value dynamically and was curious if there was a way to do this not using dynamic sql. (The query is fairly complicated and making it dynamic will hurt the performance.)

I know I can do it this way:
@sqlText = 'Select * from table order by ' + @SortColumn
exec @sqlText

is there any slick way of using a parameter in the order by statement?

Nic

Page47
Master Smack Fu Yak Hacker

2878 Posts

Posted - 2003-03-07 : 13:40:23
Dynamic ORDER BY

Jay White
{0}
Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2003-03-07 : 13:43:22
not too slick but this is a decent way:

select * from
table
order by case @field when 'field1' then field1 when 'field2' then field2 end

however, if the field types are different between the possible sort fields you need to break it out into two or more cases:

select * from
table
order by case @Field when 'textfield1' then textfield1 when 'textfield2' then textfield2 else Null END,
case @field when 'numericfield1' then numericfield1 when 'numericfield2' then numbericfield2 else null END

For numeric fields, you can alter the sort order (ASC or DESC) easily by multiplying the expression by 1 or -1 depending on what you want.

select * from
table
order by (CASE .... END) * (CASE @SortOrder when 'ASC' THEN 1 ELSE -1 END)



- Jeff
Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2003-03-07 : 13:45:25
Look at Jay's reference, but note that it doesn't handle mixed datatypes for the sort fields ....


EDIT: Read the comments from that article for more info and many other great solutions and ideas.

- Jeff

Edited by - jsmith8858 on 03/07/2003 13:52:37
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2003-03-07 : 13:52:43
And in that case, you can explicitly CAST the sort column to a character type, but you'd have to make sure of leading zeros or spaces for numerics, and use ISO date format for dates.

Another option that eliminates the datatype problem:

SELECT *, CASE @sortColumn
WHEN 'myDate' THEN myDate
WHEN 'FirstName' THEN FirstName
WHEN 'LastName' THEN LastName
ELSE ID END AS SortCol
FROM myTable
ORDER BY SortCol


The only downsides are that it adds an extra column to your output, and you need multiple expressions for multi-column sorts. But it's a little easier to maintain since you simply add extra WHEN clauses for each sort expression without having to convert anything, and you never have to alter the ORDER BY clause.

Go to Top of Page

Sitka
Aged Yak Warrior

571 Posts

Posted - 2003-03-07 : 14:01:11
Here's a model but it is still limited to single column, but resists the datatype pitfalls


CREATE PROCEDURE gettheesorted (@sortorder char(12) = 'ANY', @sortdirection char(2) = 'UP')

AS

SET NOCOUNT ON

IF @sortdirection = 'UP' ---MAIN IF

BEGIN ---main if

SELECT X.fbompart, X.fbomdesc, Z.fvendno, X.jsource, Z.company, X.fpono, X.factqty, X.fbominum, Y.jvar FROM (tables X,Y,Z in some form)

ORDER BY

case @sortorder when 'part' then X.fbompart else null end asc,
case @sortorder when 'descrip' then X.fbomdesc else null end asc,
case @sortorder when 'vendor' then Z.fvendno else null end asc,
case @sortorder when 'source' then X.jsource else null end asc,
case @sortorder when 'company' then Z.company else null end asc,
case @sortorder when 'pono' then X.fpono else null end asc,
case @sortorder when 'actqty' then X.factqty else null end asc,
case @sortorder when 'bomitemno' then X.fbominum else null end asc,
case @sortorder when 'variance' then Y.jvar else null end asc

END ---main if

ELSE ---MAIN IF This is implimented simply to allow two dynamic sort directions without using dynamic SQL

BEGIN ---main if

SELECT X.fbompart, X.fbomdesc, Z.fvendno, X.jsource, Z.company, X.fpono, X.factqty, X.fbominum, Y.jvar FROM (tables X,Y,Z in some form)

ORDER BY

case @sortorder when 'part' then X.fbompart else null end desc,
case @sortorder when 'descrip' then X.fbomdesc else null end desc,
case @sortorder when 'vendor' then Z.fvendno else null end desc,
case @sortorder when 'source' then X.jsource else null end desc,
case @sortorder when 'company' then Z.company else null end desc,
case @sortorder when 'pono' then X.fpono else null end desc,
case @sortorder when 'actqty' then X.factqty else null end desc,
case @sortorder when 'bomitemno' then X.fbominum else null end desc,
case @sortorder when 'variance' then Y.jvar else null end desc

END ---main if




Voted best SQL forum nickname...."Tutorial-D"
Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2003-03-07 : 14:14:38
quote:

And in that case, you can explicitly CAST the sort column to a character type, but you'd have to make sure of leading zeros or spaces for numerics, and use ISO date format for dates.

Another option that eliminates the datatype problem:

SELECT *, CASE @sortColumn
WHEN 'myDate' THEN myDate
WHEN 'FirstName' THEN FirstName
WHEN 'LastName' THEN LastName
ELSE ID END AS SortCol
FROM myTable
ORDER BY SortCol


The only downsides are that it adds an extra column to your output, and you need multiple expressions for multi-column sorts. But it's a little easier to maintain since you simply add extra WHEN clauses for each sort expression without having to convert anything, and you never have to alter the ORDER BY clause.





Does that eliminate the need to convert datatypes? I got errors; I think it has to do with mixing datatypes in a CASE statement, not so much the fact that the CASE expression lives in an ORDER BY clause.

example:

select case when 1=0 then 1 else 'b' end

gives an error. Am I missing something?

- Jeff

Edited by - jsmith8858 on 03/07/2003 14:15:56
Go to Top of Page

nic
Posting Yak Master

209 Posts

Posted - 2003-03-07 : 14:17:26
Greate ideas and article. It was very helpful. BUT....

I need to be able to sort on calculated fields. When I try the below code I get an invalid column name. If I sort by "ShortName" instead of "CompanyName" it works fine. But what about "PremiumVal" do I need sort by the actual calculation? (I hope not because some of the calculation are very long.)

Thanks for all your help.


SELECT
d.ShortName AS CompanyName
,ROUND(SUM(a.Premium),c.[Round]) AS PremiumVal
FROM
....
WHERE
....
GROUP BY
....
ORDER BY
CASE @OrderBy
WHEN 'CompanyName' THEN CompanyName
WHEN 'Premium' THEN PremiumVal

Nic
Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2003-03-07 : 14:24:07
Just like your calculation question; use a subquery and you'll be fine:

SELECT *
FROM
(
SELECT
d.ShortName AS CompanyName
,ROUND(SUM(a.Premium),c.[Round]) AS PremiumVal
FROM
....
WHERE
....
GROUP BY
....
) A
ORDER BY
CASE @OrderBy
WHEN 'CompanyName' THEN CompanyName
WHEN 'Premium' THEN PremiumVal

- Jeff
Go to Top of Page
   

- Advertisement -