This question already has answers here:
T-SQL Conditional Order By
(4 answers)
Closed 8 years ago.
I have a stored procedure that will accept 2 different parameters. The first parameter will determine which column I want to sort on, the second parameter will determine whether it is ASC or DESC
Create Procedure Some_SP
#sortcolumn varchar(10)
#sortorder varchar(10)
AS
Select * from empTable
Order by
CASE #sortcolumn WHEN 'First_Name' THEN fname END,
CASE #sortcolumn WHEN 'Last_Name' THEN lname END,
CASE #sortcolumn WHEN 'ID' THEN empID END,
CASE #sortorder WHEN 'ascending' THEN ASC END,
CASE #sortorder WHEN 'descending' THEN DESC END
It is giving me syntax error. How do I fix it so that I can have 2 conditions in my CASE statement?
The following will work:
Select * from empTable
Order by
CASE WHEN #sortcolumn = 'First_Name' AND #SortOrder = 'ascending' THEN fname END ASC,
CASE WHEN #sortcolumn = 'First_Name' AND #SortOrder = 'descending' THEN fname END DESC
etc...
In order to avoid typing each of these case statements by hand, you could write a "generator" script that you use to create this (especially good if the table definition would change):
SELECT
'CASE WHEN #SortColumn = ''' + C.name + ''' AND #SortOrder = ''ascending'' THEN ' + C.name + ' END ASC,' + CHAR(13) + CHAR(10) +
'CASE WHEN #SortColumn = ''' + C.name + ''' AND #SortOrder = ''descending'' THEN ' + C.name + ' END DESC,'
FROM sys.columns C
WHERE C.object_id = object_id('[Schema].[Table]')
If you want to avoid dynamic SQL and using 2x your conditions, you can use row_number
eg:
declare #t table (string varchar(50), number int)
insert #t values ('a',9),('f',2),('c',1)
declare
#sc varchar(10) = 'number', -- or 'string', etc
#so varchar(10) = 'desc' -- or 'asc'
select *
from
(
select
*,
case #sc when 'string' then ROW_NUMBER() over (order by string)
when 'number' then ROW_NUMBER() over (order by number)
end rn
from #t
) v
order by
case #so when 'desc' then -rn else rn end
You can just copy and paste and run this. I hate dynamic SQL, don't do it.
Unfortunately you'll have to duplicate the query....but it solves your specific problem.
DECLARE
#sortcolumn varchar(10),
#sortorder varchar(10)
SET #sortcolumn = 'fname'
SET #sortorder = 'DESC'
DECLARE
#Data TABLE
(
fname nvarchar(10),
lname nvarchar(10),
empID int
)
INSERT INTO #Data VALUES ('BBB', 'BBB', 2)
INSERT INTO #Data VALUES ('AAA', 'AAA', 1)
IF #sortorder = 'DESC' BEGIN
SELECT
*
FROM
#Data
ORDER BY
CASE
WHEN #sortcolumn = 'fname' THEN fname
WHEN #sortcolumn = 'lname' THEN lname
END
DESC
END ELSE BEGIN
SELECT
*
FROM
#Data
ORDER BY
CASE
WHEN #sortcolumn = 'fname' THEN fname
WHEN #sortcolumn = 'lname' THEN lname
END
END
Modifying Jon's answer to cap the ORDER BY list at just 2 instead of 2 * #columns
SELECT *
FROM MyTable
CROSS APPLY (VALUES
('First_Name',fname),
('Last_Name' ,lname),
('Id' ,ID )
) sort(SortColumn, SortValue)
WHERE SortColumn = #SortColumn
ORDER BY
CASE #SortOrder WHEN 'ascending' THEN SortValue END ASC,
CASE #SortOrder WHEN 'descending' THEN SortValue END DESC
Related
I created a stored procedure that select some data from one table
table name ( t1 )
columns ( id , a , b )
CREATE PROCEDURE spGetData
#DisplayLength INT,
#DisplayStart INT,
#SortCol INT,
#SortDir NVARCHAR(10),
#Search NVARCHAR(255) = NULL
AS
BEGIN
DECLARE #FirstRec INT, #LastRec INT
SET #FirstRec = #DisplayStart ;
SET #LastRec = #DisplayStart + #DisplayLength;
WITH CTE_Employees AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY
CASE WHEN (#SortCol = 0 AND #SortDir = 'asc') THEN id END asc,
CASE WHEN (#SortCol = 0 AND #SortDir = 'desc') THEN id END desc,
CASE WHEN (#SortCol = 1 AND #SortDir = 'asc') THEN a END asc,
CASE WHEN (#SortCol = 1 AND #SortDir = 'desc') THEN a END desc,
CASE WHEN (#SortCol = 2 AND #SortDir = 'asc') THEN b END asc,
CASE WHEN (#SortCol = 2 AND #SortDir = 'desc') THEN b END desc) AS RowNumber,
COUNT(*) OVER () AS TotalCount,
id, a, b
FROM
t1
WHERE
(#Search IS NULL
OR id LIKE '%' + #Search + '%'
OR a LIKE '%' + #Search + '%'
OR b LIKE '%' + #Search + '%')
)
SELECT *
FROM CTE_Employees
WHERE RowNumber > #FirstRec AND RowNumber <= #LastRec
END
It takes about 20 seconds to run the following
spGetData 1000 ,0,0,'desc'
which is very slow. This procedure will be called later from an ASP.NET MVC project and the result will be displayed using jQuery datatables.
How can I improve the performance of it?
First off, lose CTE. This is way too simple query for CTE.
CREATE PROCEDURE spGetData
#DisplayLength int,
#DisplayStart int,
#SortCol int,
#SortDir nvarchar(10),
#Search nvarchar(255) = NULL
AS
BEGIN
SELECT
COUNT(*) OVER () AS TotalCount,
id,
a,
b
FROM t1
WHERE
(#Search IS NULL OR
id LIKE '%'+#Search+'%' OR
a LIKE '%'+#Search+'%' OR
b LIKE '%'+#Search+'%')
ORDER BY
CASE
WHEN #SortDir = 'ASC' THEN
CASE #SortCol
WHEN 0 THEN id
WHEN 1 THEN a
WHEN 2 THEN b
END
END desc,
CASE
WHEN #SortDir = 'desc' THEN
CASE #SortCol
WHEN 0 THEN id
WHEN 1 THEN a
WHEN 2 THEN b
END
END DESC
OFFSET #DisplayStart ROWS
FETCH NEXT #DisplayLength ROWS ONLY
END
This should be faster, but one more remark. LIKE searching within middle of string ('%'+#Search+'%') can't use any indexing and will always be slow - especially on 2M rows and even worse - doing that on three different columns. It simply has to do a full table scan.
Adding additional conditions (which are not LIKE) would improve performance.
I'm using SQL Server 2014 management studio and I wanted to create a stored procedure but I have a problem at the very end of the code where the error "Incorrect syntax near OFFSET" appears.
CREATE PROCEDURE [dbo].[GetGamesPlayed]
#gameSession int,
#datestart datetime,
#dateend datetime,
#orderBy nvarchar(50) = 'email',
#sortOrder nvarchar(4) = 'asc',
#search nvarchar(50) = '',
#startRow int = 0,
#rows int = 2147483647
AS
BEGIN
SET NOCOUNT ON;
SELECT t.*,
COUNT(*) OVER() AS filteredRows,
(SELECT COUNT(id) FROM gameplayed WHERE gameplayed.id_GameSession = #gameSession) AS totalRows
FROM (SELECT
DISTINCT GamesTable.[Game ID],
GamesTable.[Rep Id],
GamesTable.[User Id],
GamesTable.[Date],
GamesTable.[Email],
GamesTable.[Name],
GamesTable.[Phone Number],
GamesTable.[Tokens Played],
CASE
WHEN prizewon.pending = 1 THEN 'Pending'
WHEN prizewon.skillTestingQCorrect = 1 AND prizewon.rulesAccepted = 1 THEN 'Yes'
ELSE 'No'
END AS [Won]
FROM PrizeWon
RIGHT OUTER JOIN (
SELECT
GamePlayed.id AS [Game ID],
GamePlayed.playedOn AS [Date],
users.repId AS [Rep Id],
users.id AS [User Id],
users.fullName AS [Name],
users.email AS [Email],
users.phoneNumber AS [Phone Number],
GamePlayed.tokensPlayed AS [Tokens Played]
FROM GamePlayed
INNER JOIN Users on GamePlayed.id_Users = Users.id
WHERE GamePlayed.id_GameSession = #gameSession) AS GamesTable ON GamesTable.[Game ID] = prizewon.id_GamePlayed
WHERE GamesTable.Date >= #datestart
AND GamesTable.Date <= #dateend
AND ( GamesTable.[Email] LIKE '%' + #search + '%'
OR GamesTable.[Rep Id] LIKE '%' + #search + '%'
OR GamesTable.[Name] LIKE '%' + #search + '%'
OR GamesTable.[Game ID] LIKE '%' + #search + '%'
)
) t
--order by cases must be split into datatypes
ORDER BY
CASE WHEN #sortOrder = 'asc' THEN
CASE #orderBy -- nvarchar
WHEN 'repid' THEN t.[Rep Id]
WHEN 'name' THEN t.[Name]
WHEN 'email' THEN t.[Email]
WHEN 'phone' THEN t.[Phone Number]
WHEN 'won' THEN t.Won
END
END ASC,
CASE WHEN #sortOrder = 'asc' THEN
CASE #orderBy --date
WHEN 'date' THEN t.Date
END
END ASC,
CASE WHEN #sortOrder = 'asc' THEN
CASE #orderBy --int
WHEN 'id' THEN t.[Game ID]
WHEN 'tokens' THEN t.[Tokens Played]
END
END ASC,
CASE WHEN #sortOrder = 'desc' THEN
CASE #orderBy -- nvarchar
WHEN 'repid' THEN t.[Rep Id]
WHEN 'name' THEN t.[Name]
WHEN 'email' THEN t.[Email]
WHEN 'phone' THEN t.[Phone Number]
WHEN 'won' THEN t.Won
END
END DESC,
CASE WHEN #sortOrder = 'desc' THEN
CASE #orderBy --date
WHEN 'date' THEN t.Date
END
END DESC,
CASE WHEN #sortOrder = 'desc' THEN
CASE #orderBy --int
WHEN 'id' THEN t.[Game ID]
WHEN 'tokens' THEN t.[Tokens Played]
END
END DESC
OFFSET #startRow ROWS FETCH NEXT #rows ROWS ONLY
END
I have seen in other posts that the error may appear because the OFFSET is not after an ORDER BY, but in this case it is after one ORDER BY.
Another thing that I saw is that SQL Server 2008 doesn't support OFFSET, but I'm using 2014.
I have also checked that the variables that I'm using are declared and they all are...
Its pretty much the only error that is keeping me from creating the procedure. If anyone could help I'll be very greatful!
After a little research I used "SELECT ##version" and found out that my database version was 2008, which doesn't support OFFSET.
A quick update to version 2012 solved the issue.
I am creating below stored procedure.
declare #PageNum as Int
declare #PerPageResult as Int
declare #StartDate as varchar(25)
declare #EndDate as varchar(25)
declare #SortType as Varchar(50)
declare #SortDirection as Varchar(4)
set #PageNum=1
set #PerPageResult=20
set #StartDate='2008-02-08'
set #EndDate='2015-02-08'
set #SortType='RegDate'
set #SortDirection='Desc'
declare #Temp Table(RowNum int, RegDate Date, Registered int, Female int, Male int, [Join] int, Rebill int, TotalPointsEarned int, Expire int)
declare #sort varchar(50)
Insert into #Temp
Select ROW_NUMBER() over (order by #SortType+' '+#SortDirection) As RowNum, * From (
SELECT
CAST(m.registrationdate AS Date) as RegDate,
count(m.id) Registered,
count(CASE WHEN m.gender='F' then 'F' end) As Female,
count(CASE WHEN m.gender='M' then 'M' end) As Male
count(CASE WHEN p.paymenttransactiontype='N' then 'N' end) As [Join],
count(CASE WHEN p.paymenttransactiontype='R' then 'R' end) As Rebill,
count(m.tokensearned) As TotalPointsEarned,
count(CASE WHEN p.paymenttransactiontype='E' then 'E' end) As Expire
from member m
join payment p on m.id=p.id_member
join user_role u on u.member_id=m.id
where u.role_id <> 3
and CAST(m.registrationdate AS Date) > #StartDate and CAST(m.registrationdate AS Date) < #EndDate
GROUP BY CAST(m.registrationdate AS Date)
) as aa
Select * from #Temp Where RowNum>((#PageNum-1)*#PerPageResult) and RowNum<=#PerPageResult * #PageNum
Order by #SortType+' '+#SortDirection
In above when i pass the Order by clause dynamically, its not sorting the data properly but when i write column name explicitly, it works fine. Might be its taking #SortType+' '+#SortDirection as varchar rather than Date
I tried writing Order by case when (#Sort='RegDate' and #SortDirection='Desc') Then RegDate End Desc, but it didn't work
How can i pass order by dynamically here.
Edit:
#Andomar: I tried your provided solution and added one more field for Date type. And it didn't work too.
below is what i did.
create table t1 (id int, name varchar(50), dt date);
insert t1 values
(1, 'Chihiro Ogino','2009-02-08'),
(2, 'Spirit of the Kohaku River','2008-02-08'),
(3, 'Yubaba','2012-02-08');
declare #sortColumn varchar(50) = 'dt'
declare #sortOrder varchar(50) = 'ASC'
select *
from t1
order by
case
when #sortOrder <> 'ASC' then 0
when #sortColumn = 'id' then id
end ASC
, case
when #sortOrder <> 'ASC' then ''
when #sortColumn = 'name' then name
end ASC
, case
when #sortOrder <> 'ASC' then ''
when #sortColumn = 'dt' then name
end ASC
, case
when #sortOrder <> 'DESC' then 0
when #sortColumn = 'id' then id
end DESC
, case
when #sortOrder <> 'DESC' then ''
when #sortColumn = 'name' then name
end DESC
, case
when #sortOrder <> 'DESC' then ''
when #sortColumn = 'dt' then name
end DESC
You can use a complicated order by clause. That requires one case for each sort direction and each data type. With this example dataset:
create table t1 (id int, name varchar(50), created date);
insert t1 values
(1, 'Chihiro Ogino', '2012-01-01'),
(2, 'Spirit of the Kohaku River', '2012-01-03'),
(3, 'Yubaba', '2012-01-02');
You could use an order by clause like:
declare #sortColumn varchar(50) = 'created'
declare #sortOrder varchar(50) = 'DESC'
select *
from t1
order by
case
when #sortOrder <> 'ASC' then 0
when #sortColumn = 'id' then id
end ASC
, case
when #sortOrder <> 'ASC' then ''
when #sortColumn = 'name' then name
end ASC
, case
when #sortOrder <> 'ASC' then cast(null as date)
when #sortColumn = 'created' then created
end ASC
, case
when #sortOrder <> 'DESC' then 0
when #sortColumn = 'id' then id
end DESC
, case
when #sortOrder <> 'DESC' then ''
when #sortColumn = 'name' then name
end DESC
, case
when #sortOrder <> 'DESC' then cast(null as date)
when #sortColumn = 'created' then created
end DESC
Working example at SQL Fiddle.
Another option is to create the query dynamically, and run it with exec. For example:
declare #sql nvarchar(max)
set #sql = 'select * from YourTable order by ' + #sortColumn + ' ' + #sortDir
exec (#sql)
#Andomar's answer help solve a similar issue. I needed to sort on any number of 23 different columns, in any order. I ended up with the following:
create table sorting(ID int, columnName varchar(50), sort varchar(10), position int)
insert into sorting
values(1,'column1','DESC',1),
(1,'column2','ASC',2),
...
(1,'columnN','DESC',N)
Adding parameter #sort to the SP to identify the entries in sorting:
ORDER BY ISNULL(STUFF((SELECT ', ' + a.columnName + ' ' + a.sort
FROM sorting a
WHERE a.ID = #sort
ORDER BY a.position ASC
FOR XML PATH('')), 1, 2, ''),NULL)
There are two basic approaches to building dynamically orderable stored procedures:
Pass in the ORDER BY clause as a parameter to the stored procedure. In the stored procedure, build up the SQL statement in a string and then execute this statement using EXEC or sp_ExecuteSql.
-- This Method is used when your Column names are dynamic
-- We need to create a dynamic query and Execute it as shown below.
CREATE PROCEDURE getEmployees ( #OrderByClause varchar(100) ) AS
-- Create a variable #SQLStatement
DECLARE #SQLStatement varchar(255)
-- Enter the dynamic SQL statement into the
-- variable #SQLStatement
SELECT #SQLStatement = 'SELECT EmployeeID, FirstName, LastName, SSN, Salary
FROM Employees ORDER BY '+ #OrderByClause+''
-- Execute the SQL statement
EXEC(#SQLStatement)
Pass in the column to sort by and then use a CASE statement in the ORDER BY clause to order the results according to the input parameter value.
--This method is used when you column name is not dynamic
SELECT EmployeeID, FirstName, LastName, SSN, Salary
FROM Employees
ORDER BY
CASE WHEN #ColumnName='LastName' THEN LastName
WHEN #ColumnName='Salary' THEN CONVERT(varchar(50), Salary)
WHEN #ColumnName='SSN' THEN SSN
END
something like this should work :
ORDER BY
CASE WHEN #SortDirection = 'ASC' THEN #SortType END ASC,
CASE WHEN #SortDirection = 'DESC' THEN #SortType END DESC
Hi the below query is a prototype of a bigger complex query
The problem is that i should be able sort any column in any order (i.e. ASC and DESC) based on user input.
CREATE table #Table1(
Name varchar(10) PRIMARY key,
DOB DateTime,
Rate numeric(10,2)
)
INSERT INTO #Table1 (Name,DOB,Rate) values ('Name1','2/2/2012',10.23)
INSERT INTO #Table1 (Name,DOB,Rate) values ('Name2','3/2/2012',120.23)
INSERT INTO #Table1 (Name,DOB,Rate) values ('Name3','4/2/2012',110.23)
INSERT INTO #Table1 (Name,DOB,Rate) values ('Name4','5/2/2012',140.23)
INSERT INTO #Table1 (Name,DOB,Rate) values ('Name15','6/2/2012',130.23)
INSERT INTO #Table1 (Name,DOB,Rate) values ('Name6','2/21/2012',1120.23)
Declare #SortColumn varchar(10)
DECLARE #SortExpression varchar (10)
SET #SortColumn = 'DOB'
SET #SortExpression = 'DESC' -- Need to sort in both ASC and DESC
Select
Name,
DOB,
Rate,
ROW_NUMBER() OVER
(ORDER BY
CASE WHEN #SortColumn = 'Name' then Name
WHEN #SortColumn = 'DOB' THEN DOB
WHEN #SortColumn = 'Rate' THEN Rate
END + #SortExpression
) AS RowNumber
FROM
#Table1
Looks like you need to CAST() and CONVERT() the items in the CASE to get it to work:
Declare #SortColumn varchar(10)
DECLARE #SortExpression varchar (10)
SET #SortColumn = 'DOB'
SET #SortExpression = 'DESC' -- Need to sort in both ASC and DESC
Select
Name,
DOB,
Rate,
ROW_NUMBER() OVER
(ORDER BY
CASE WHEN #SortColumn = 'Name' then Name
WHEN #SortColumn = 'DOB' THEN convert(char(10), DOB, 120)
WHEN #SortColumn = 'Rate' THEN Cast(Rate as varchar(10))
END ASC
) AS RowNumberASC,
ROW_NUMBER() OVER
(ORDER BY
CASE WHEN #SortColumn = 'Name' then Name
WHEN #SortColumn = 'DOB' THEN convert(char(10), DOB, 120)
WHEN #SortColumn = 'Rate' THEN Cast(Rate as varchar(10))
END DESC
) AS RowNumberDESC
FROM Table1
See SQL Fiddle with Demo
As #Martin pointed out the ASC, DESC cannot be parameterized.
If you need to switch between ASC and DESC dynamically, you will have to use a dynamic statement.
SQL Fiddle here. Be aware of SQL Injection!
EXECUTE(' SELECT Name, DOB, Rate,'
+ ' ROW_NUMBER() OVER( ORDER BY ' + #SortColumn + ' ' + #SortExpression
+ ' ) AS RowNumber'
+ ' FROM Table1');
If your query is complex, consider putting it into a view and select from that view to allow compile-time checking of that part.
I have the following stored procedure which can be sorted ascending and descending on TemplateName,CreatedOn and UploadedBy. The following SP when runs doesnot sort records.if i replace 2,3,4 by columnname, i got an error message "Conversion failed when converting the nvarchar value 'Test Template' to data type int.".Please suggest how to achieve sorting.
CREATE PROCEDURE [dbo].[usp_SEL_GetRenderingTemplate]
(
#facilityID INT,
#sortOrder VARCHAR(5),
#sortExpression VARCHAR(100),
#errorCode INT OUTPUT
)
AS
BEGIN
SET NOCOUNT ON ;
BEGIN TRY
SET #sortOrder = CASE #sortOrder
WHEN 'Ascending' THEN 'ASC'
WHEN 'Descending' THEN 'DESC'
ELSE 'ASC'
END
SELECT TemplateID,
TemplateName,
CreatedOn,
( [user].LastName + ' ' + [user].FirstName ) AS UploadedBy
FROM Templates
INNER JOIN [user] ON [user].UserID = Templates.CreatedBy
WHERE facilityid = #facilityID
ORDER BY CASE WHEN #sortExpression = 'TemplateName'
AND #sortOrder = 'ASC' THEN 2
WHEN #sortExpression = 'CreatedOn'
AND #sortOrder = 'ASC' THEN 3
WHEN #sortExpression = 'UploadedBy'
AND #sortOrder = 'ASC' THEN 4
END ASC,
CASE WHEN #sortExpression = 'TemplateName'
AND #sortOrder = 'DESC' THEN 2
WHEN #sortExpression = 'CreatedOn'
AND #sortOrder = 'DESC' THEN 3
WHEN #sortExpression = 'UploadedBy'
AND #sortOrder = 'DESC' THEN 4
END DESC
SET #errorCode = 0
END TRY
BEGIN CATCH
SET #errorCode = -1
DECLARE #errorMsg AS VARCHAR(MAX)
DECLARE #utcDate AS DATETIME
SET #errorMsg = CAST(ERROR_MESSAGE() AS VARCHAR(MAX))
SET #utcDate = CAST(GETUTCDATE() AS DATETIME)
EXEC usp_INS_LogException 'usp_SEL_GetFacilityWorkTypeList',
#errorMsg, #utcDate
END CATCH
END
The dynamic ordering has to be of the same datatype. Here is an example of something that I use to case order three different datatypes - integer, date (ascending and descending), and string. This may not work for your situation, but at least you can see some techniques for casting to a common datatype.
...
ORDER BY
Case Parent.RankTypeID
When 0 Then dbo.Documents.Rank
When 1 Then Convert(int, dbo.Documents.DateStart, 112)
When 2 Then (1 - Convert(int, dbo.Documents.DateStart, 112))
When 3 Then Cast(dbo.Documents.Title as sql_variant)
End
Note:
112 is a date format of YYYYMMDD - useful for ordering.
We perform a similar sort of dynamic ordering in one of our products.
The only real different to your code is firstly, we don't use the live join.
We create a temporary table, so we can perform paging, and then apply the order.
We also use ints for ordering, cuts down on the overhead of string comparison.
It does make your SQL a bit longer, but this approach is definitely faster for the Query Optimiser. Also, and more importantly, I don't think you can mix types in Switch blocks, for ordering, so to follow your original code, you'd have to CONVERT all your data to the same time, which defeats the object :(
So you'd have
DECLARE #temp TABLE(ID int identity(1,1), TemplateID int, TemplateName nvarchar(100), CreatedOn datetime, UploadedBy nvarchar(100))
INSERT INTO #temp(TemplateID, TemplateName, CreatedOn, UploadedBy)
SELECT TemplateID,
TemplateName,
CreatedOn,
( [user].LastName + ' ' + [user].FirstName ) AS UploadedBy
FROM Templates
INNER JOIN [user] ON [user].UserID = Templates.CreatedBy
WHERE facilityid = #facilityID
Then:
IF #SortOrder = 1 --'ASC'
BEGIN
IF #sort = 2
Select *
From #Temp
Order by TemplateName ASC
ELSE IF #sort = 3
Select *
From #Temp
Order By CreatedBy ASC
-- and so on...
END
ELSE -- descending
BEGIN
-- Ad. Inf.
END
Delete
From #Temp
WHERE ID < #pageStart or ID > #pageStart + #pageSize
The following SP when runs doesnot
sort records.if i replace 2,3,4 by
columnname,
You shouldn't replace 2, 3, 4 in the ORDER BY clause by the column name. When you call the procedure just pass the column you want to sort by as the 3rd parameter.
EXEC [dbo].[usp_SEL_GetRenderingTemplate] 1,'Ascending','CreatedOn',#vErrorCode
The CASE will then evaluate the query to something like
...ORDER BY 3 DESC
which sorts the query by the 3rd column in the SELECT clause (i.e. CreatedOn)
The problem is that in CASE clauses the return values must have the same data type.
You can work around this problem by using multiple CASE statements http://www.extremeexperts.com/sql/articles/CASEinORDER.aspx
Or casting everything to the same data type.