SQL orderby / case issue: orderdirection fail - sql-server-2008

I got a stored procedure that delivers a table of students, and it needs to order by surname, name etc... it also needs to sort ascending, descending, depending on the parameter #orderby...
code:
ORDER BY
CASE
WHEN #orderby = 'studentkey' THEN Studentkey END ASC,
CASE
WHEN #orderby = 'studentkey' and #desc = 1 THEN Studentkey END DESC,
CASE
WHEN #orderby = 'initials' THEN Initials END ASC,
CASE
WHEN #orderby = 'initials' and #desc = 1 THEN Initials END DESC,
CASE
WHEN #orderby = 'firstname' THEN Firstname END ASC,
CASE
WHEN #orderby = 'firstname' and #desc = 1 THEN Firstname END DESC,
CASE
WHEN #orderby = 'nickname' THEN Nickname END ASC,
CASE
WHEN #orderby = 'nickname' and #desc = 1 THEN Nickname END DESC,
CASE
WHEN #orderby = 'insertion' THEN Insertion END ASC,
CASE
WHEN #orderby = 'insertion' and #desc = 1 THEN Insertion END DESC,
CASE
WHEN #orderby = 'surname' THEN Surname END ASC,
CASE
WHEN #orderby = 'surname' and #desc = 1 THEN Surname END DESC
NED
There is a difference in output between #desc = 1 and #desc = 0, but not what i desire...
Does anyone have a solution?

Try this:
CASE
WHEN #orderby = 'studentkey' and #desc = 0 THEN Studentkey END ASC,
CASE
WHEN #orderby = 'studentkey' and #desc = 1 THEN Studentkey END DESC,
...

Related

Multiple case condition in sql order by clause?

How to make conditional ordering for two or more columns..I just tried the below code. is there any better way of writing this?
CASE WHEN d.receipt IS NULL AND c.receipt =1 then pr.account END ASC,
CASE WHEN d.receipt =1 AND c.receipt IS NULL then pr.account END ASC,
CASE WHEN d.receipt =1 AND c.receipt =0 then pr.account END ASC,
CASE WHEN d.receipt =1 AND c.receipt =1 then pr.account END ASC,
CASE WHEN d.receipt IS NULL AND c.receipt IS NULL THEN pr.amount END DESC,
CASE WHEN d.receipt IS NULL AND c.receipt =0 THEN pr.amount END DESC,
CASE WHEN d.receipt =0 AND c.receipt IS NULL THEN pr.amount END DESC,
CASE WHEN d.receipt =0 AND c.receipt =0 THEN pr.amount END DESC,
CASE WHEN d.receipt =0 AND c.receipt =1 THEN pr.amount END DESC
You could try this:
CASE WHEN d.receipt = 1 THEN pr.account
WHEN d.receipt = 0 THEN -pr.amount
WHEN c.receipt = 1 THEN pr.account
ELSE -pr.amount
END
It always sorts ascending but in some cases on the negative amount which of course results in descending.
The manual https://dev.mysql.com/doc/refman/5.7/en/case.html says:
"Each WHEN clause search_condition expression is evaluated until one is true, at which point its corresponding THEN clause statement_list executes. If no search_condition is equal, the ELSE clause statement_list executes, if there is one."
This implies that the expressions are evaluated in the order they are specified.
In other words, the 3rd condition (c.receipt = 1) is evaluated only if d.receipt is NULL.

order by not working in stored procedure mysql

select
tr.TransactionId as TxnIdentifier,
m.MerchantName as MerchantName,
case
when tr.ChannelType=2 then 'ACH'
when tr.ChannelType=3 then 'CC'
when tr.ChannelType=4 then 'Debit'
else null
end as ChannelType,
tr.CaptureAmount as CaptureAmount,
case when tr.OperationType=0 then 'Sale'
when tr.OperationType=1 then 'Verify only'
when tr.OperationType=2 then 'ForceSale'
when tr.OperationType=3 then 'Adjust'
when tr.OperationType=4 then 'Activate'
when tr.OperationType=5 then 'Deactivate'
when tr.OperationType=6 then 'Reload'
when tr.OperationType=7 then 'Refund'
when tr.OperationType=8 then 'Inquire'
else null end as TxnType,
case when tr.TransactionStatus=0 then 'Created'
when tr.TransactionStatus=1 then 'Pending'
when tr.TransactionStatus=2 then 'Authorized'
when tr.TransactionStatus=3 then 'Posted'
when tr.TransactionStatus=4 then 'Accepted'
when tr.TransactionStatus=5 then 'Failed'
when tr.TransactionStatus=6 then 'Returned'
when tr.TransactionStatus=7 then 'Chargeback'
when tr.TransactionStatus=8 then 'Void'
when tr.TransactionStatus=9 then 'Refunded'
when tr.TransactionStatus=10 then 'Approved'
when tr.TransactionStatus=11 then 'Void attempted'
when tr.TransactionStatus=12 then 'Refund attempted'
when tr.TransactionStatus=13 then 'Hold'
when tr.TransactionStatus=14 then 'Denied'
when tr.TransactionStatus=15 then 'Settlement hold'
when tr.TransactionStatus=16 then 'Success'
when tr.TransactionStatus=17 then 'Retried'
when tr.TransactionStatus=100 then 'Unknown'
else null end as TxnStatus,
tr.PreAuthCode as AuthCode,
DATE_FORMAT(tr.TransactionDate, '%m-%d-%Y %H:%i:%s') as TransactionDate,
case when tr.OperationType='7' then tr.Amount
else null end as RefundAmount,
case when tr.OperationType='7'
then DATE_FORMAT(tr.TransactionDate, '%m-%d-%Y %H:%i:%s')
else null end as RefundedOn,
tr.TraceNumber as TraceNumber
from TransactionEntity tr
inner join `enter code here`DOMAIN.Merchant m on m.Id=tr.MerchantId where 1=1
and (tr.MerchantId = merchantId or merchantId=0)
and (tr.ChannelType = channelType or channelType=0)
And (tr.TransactionDate >= startDate or startDate is null)
And (tr.TransactionDate <= endDate or endDate is null)
ORDER BY
CASE WHEN sortField = 'TransactionDate' AND sortDirection='ASC' THEN TransactionDate END ASC,
CASE WHEN sortField = 'TransactionDate' AND sortDirection='DESC' THEN TransactionDate END DESC
If I apply order by clause outside the stored procedure it works fine but inside the sp it didn't work (applying order by desc on TransactionDate not working)
Try creating your stored procedure like below then
DELIMITER //
CREATE PROCEDURE select_whatever(sortField VARCHAR(20), sortDirection CHAR(4))
BEGIN
DECLARE select_clause TEXT;
DECLARE order_by_clause VARCHAR(100);
SET select_clause = "
select
tr.TransactionId as TxnIdentifier,
m.MerchantName as MerchantName,
case
when tr.ChannelType=2 then 'ACH'
when tr.ChannelType=3 then 'CC'
when tr.ChannelType=4 then 'Debit'
else null
end as ChannelType,
tr.CaptureAmount as CaptureAmount,
case
when tr.OperationType=0 then 'Sale'
when tr.OperationType=1 then 'Verify only'
when tr.OperationType=2 then 'ForceSale'
when tr.OperationType=3 then 'Adjust'
when tr.OperationType=4 then 'Activate'
when tr.OperationType=5 then 'Deactivate'
when tr.OperationType=6 then 'Reload'
when tr.OperationType=7 then 'Refund'
when tr.OperationType=8 then 'Inquire'
else null
end as TxnType,
case
when tr.TransactionStatus=0 then 'Created'
when tr.TransactionStatus=1 then 'Pending'
when tr.TransactionStatus=2 then 'Authorized'
when tr.TransactionStatus=3 then 'Posted'
when tr.TransactionStatus=4 then 'Accepted'
when tr.TransactionStatus=5 then 'Failed'
when tr.TransactionStatus=6 then 'Returned'
when tr.TransactionStatus=7 then 'Chargeback'
when tr.TransactionStatus=8 then 'Void'
when tr.TransactionStatus=9 then 'Refunded'
when tr.TransactionStatus=10 then 'Approved'
when tr.TransactionStatus=11 then 'Void attempted'
when tr.TransactionStatus=12 then 'Refund attempted'
when tr.TransactionStatus=13 then 'Hold'
when tr.TransactionStatus=14 then 'Denied'
when tr.TransactionStatus=15 then 'Settlement hold'
when tr.TransactionStatus=16 then 'Success'
when tr.TransactionStatus=17 then 'Retried'
when tr.TransactionStatus=100 then 'Unknown'
else null
end as TxnStatus,
tr.PreAuthCode as AuthCode,
DATE_FORMAT(tr.TransactionDate, '%m-%d-%Y %H:%i:%s') as TransactionDate,
case
when tr.OperationType='7' then tr.Amount
else null
end as RefundAmount,
case
when tr.OperationType='7'
then DATE_FORMAT(tr.TransactionDate, '%m-%d-%Y %H:%i:%s')
else null
end as RefundedOn,
tr.TraceNumber as TraceNumber
from TransactionEntity tr
inner join `enter code here`DOMAIN.Merchant m on m.Id=tr.MerchantId where 1=1
and (tr.MerchantId = merchantId or merchantId=0)
and (tr.ChannelType = channelType or channelType=0)
And (tr.TransactionDate >= startDate or startDate is null)
And (tr.TransactionDate <= endDate or endDate is null)
";
SET order_by_clause = "ORDER BY";
IF sortField = "TransactionDate" AND sortDirection="ASC" THEN
SET order_by_clause = CONCAT(order_by_clause, " TransactionDate ASC")
ELSEIF sortField = "TransactionDate" AND sortDirection="DESC" THEN
SET order_by_clause = CONCAT(order_by_clause, " TransactionDate DESC")
END IF
SET #dynamic_sql = CONCAT(select_clause, ' ', order_by_clause);
PREPARE select_whatever_statement
FROM #dynamic_sql;
EXECUTE select_whatever_statement;
DEALLOCATE PREPARE select_whatever_statement;
END //
DELIMITER ;

Mysql server side paging , sorting

Hello I have one table in database which contains multiple columns , more than 20 and it contains many records about 2 millions
The table has one primary key : Col1 and it is also the index for my table
, For some reasons , the data type for that column is varchar(200).
I am implementing server side paging ,sorting and later (filtering)
I face a problem in performance , here is my procedure
DELIMITER $$
CREATE DEFINER=`master`#`%` PROCEDURE `spGetData`(
IN DisplayStart int ,
IN SortCol int ,
IN SortDir nvarchar(10),
IN Search nvarchar(255)
)
BEGIN
DECLARE FirstRec int;
DECLARE LastRec int;
SET FirstRec = DisplayStart;
select
col1,col2,col3,col4,col6,col7,col8,col9,col10,col11
col12,col13,col14,col15,col16,col17,col18,col19,col20
col21,
( select count(*) from myTable) as filtered
from myTable
order by
case When (#SortCol = 0 and #SortDir = 'asc') then col1 end asc ,
case When (#SortCol = 0 and #SortDir = 'desc') then col1 end desc ,
case When (#SortCol = 1 and #SortDir = 'asc') then col2 end asc ,
case When (#SortCol = 1 and #SortDir = 'desc') then col2 end desc ,
case When (#SortCol = 2 and #SortDir = 'asc') then col3 end asc ,
case When (#SortCol = 2 and #SortDir = 'desc') then col3 end desc ,
case When (#SortCol = 3 and #SortDir = 'asc') then col4 end asc ,
case When (#SortCol = 3 and #SortDir = 'desc') then col4 end desc ,
case When (#SortCol = 4 and #SortDir = 'asc') then col5 end asc ,
case When (#SortCol = 4 and #SortDir = 'desc') then col5 end desc ,
case When (#SortCol = 5 and #SortDir = 'asc') then col6 end asc ,
case When (#SortCol = 5 and #SortDir = 'desc') then col6 end desc ,
case When (#SortCol = 6 and #SortDir = 'asc') then col7 end asc ,
case When (#SortCol = 6 and #SortDir = 'desc') then col7 end desc ,
case When (#SortCol = 7 and #SortDir = 'asc') then col8 end asc ,
case When (#SortCol = 7 and #SortDir = 'desc') then col8 end desc ,
case When (#SortCol = 8 and #SortDir = 'asc') then col9 end asc ,
case When (#SortCol = 8 and #SortDir = 'desc') then col9 end desc ,
case When (#SortCol = 9 and #SortDir = 'asc') then col10 end asc ,
case When (#SortCol = 9 and #SortDir = 'desc') then col10 end desc ,
case When (#SortCol = 10 and #SortDir = 'asc') then col11 end asc ,
case When (#SortCol = 10 and #SortDir = 'desc') then col11 end desc ,
case When (#SortCol = 11 and #SortDir = 'asc') then col12 end asc ,
case When (#SortCol = 11 and #SortDir = 'desc') then col12 end desc ,
case When (#SortCol = 12 and #SortDir = 'asc') then col13 end asc ,
case When (#SortCol = 12 and #SortDir = 'desc') then col13 end desc ,
case When (#SortCol = 13 and #SortDir = 'asc') then col14 end asc ,
case When (#SortCol = 13 and #SortDir = 'desc') then col14 end desc ,
case When (#SortCol = 14 and #SortDir = 'asc') then col15 end asc ,
case When (#SortCol = 14 and #SortDir = 'desc') then col15 end desc ,
case When (#SortCol = 15 and #SortDir = 'asc') then col16 end asc ,
case When (#SortCol = 15 and #SortDir = 'desc') then col16 end desc ,
case When (#SortCol = 16 and #SortDir = 'asc') then col17 end asc ,
case When (#SortCol = 16 and #SortDir = 'desc') then col17 end desc ,
case When (#SortCol = 17 and #SortDir = 'asc') then col18 end asc ,
case When (#SortCol = 17 and #SortDir = 'desc') then col18 end desc ,
case When (#SortCol = 18 and #SortDir = 'asc') then col19 end asc ,
case When (#SortCol = 18 and #SortDir = 'desc') then col19 end desc ,
case When (#SortCol = 19 and #SortDir = 'asc') then col20 end asc ,
case When (#SortCol = 19 and #SortDir = 'desc') then col20 end desc ,
case When (#SortCol = 20 and #SortDir = 'asc') then col21 end asc ,
case When (#SortCol = 20 and #SortDir = 'desc') then col21 end desc ,
limit FirstRec,10;
END
The query is very slow and it gives a buffer size problem.
If i remove the order by clause , it becomes very fast.
So my questions are
1- How can i enhance this query and make sorting for millions of rows act fast?
2- Later i will apply filtering using a where clause for multiple columns , how can i avoid any performance issue?
The ORDER BY should be constructed (concat, prepare, execute, deallocate) instead of having that huge expression that cannot use any index.
It is possible, but not realistic, to add INDEX(col0), INDEX(col1), ... so that the prepared statement will be fast in all 21 cases. Pick the important ones and don't provide the rest to the end-user.
Don't use OFFSET to paginate; instead 'remember where you left off'.
Where's the filtering? It is likely to interfere with the tips I have already given you.
VARCHAR(200) is usually unwise for the PRIMARY KEY.
Will the user be able to specify sorting on two columns? Filtering on date ranges? Other things? (Please provide the real SHOW CREATE TABLE if you want to get into more details.)
Have you 'normalized' any columns? That is, move large, frequently repeated, values into other tables.

Why CASE statement doesn't work without nesting? [duplicate]

This question already has answers here:
Dynamic Sorting within SQL Stored Procedures
(15 answers)
Closed 5 years ago.
I have a requirement to sort the results dynamically based on the column selection. I know that only first query below works and 2nd one fails. But am unable to understand why it fails, as per my understanding based on #SortDirection value it should give ASC or DESC, which will get appended to the earlier CASE which is returning column name. Can you please explain why it fails?
create table EmpData
(
EmpID int identity,
FName varchar(20),
LName varchar(20),
Email varchar(30),
City varchar(20),
DOB date
)
GO
INSERT INTO EmpData values ('Mark','Smith','Mark.s#email.com','London','02-Jun-1980')
INSERT INTO EmpData values ('Mark','Marsh','Mark.m#email.com','Paris','02-Jul-1981')
INSERT INTO EmpData values ('Steve','Elgar','Steve.e#email.com','Canada','12-Jun-1980')
INSERT INTO EmpData values ('Michael','Jones','Michael.j#email.com','France','22-Jan-1980')
GO
----------QUERY 1--------
DECLARE #SortByColumn varchar(20)='City',
#SortDirection varchar(5)='ASC'
SELECT EmpID,FName AS FirstName, LName AS LastName, Email, City, DOB as 'Date-Of-Birth'
FROM EmpData
ORDER BY
CASE #SortDirection WHEN 'ASC' THEN
CASE #SortByColumn
WHEN 'FirstName' THEN FName
WHEN 'LastName' THEN LName
WHEN 'Email' THEN Email
WHEN 'City' THEN City
ELSE ''
END
END,
CASE #SortDirection WHEN 'DESC' THEN
CASE #SortByColumn
WHEN 'FirstName' THEN FName
WHEN 'LastName' THEN LName
WHEN 'Email' THEN Email
WHEN 'City' THEN City
ELSE ''
END
END DESC
GO
----------QUERY 2--------
DECLARE #SortByColumn varchar(20)='City',
#SortDirection varchar(5)='ASC'
SELECT EmpID,FName AS FirstName, LName AS LastName, Email, City, DOB as 'Date-Of-Birth'
FROM EmpData
ORDER BY
CASE #SortByColumn
WHEN 'FirstName' THEN FName
WHEN 'LastName' THEN LName
WHEN 'Email' THEN Email
WHEN 'City' THEN City
ELSE ''
END
CASE #SortDirection
WHEN 'DESC' THEN DESC
ELSE ASC
END
Try like this
DECLARE #SortByColumn varchar(20)='City',
#SortDirection varchar(5)='asc'
;WITH CTE
AS
(
SELECT
Seq1 = ROW_NUMBER() OVER(ORDER BY
CASE #SortByColumn
WHEN 'FirstName' THEN FName
WHEN 'LastName' THEN LName
WHEN 'Email' THEN Email
WHEN 'City' THEN City
ELSE ''
END ASC),
Seq2 = ROW_NUMBER() OVER(ORDER BY
CASE #SortByColumn
WHEN 'FirstName' THEN FName
WHEN 'LastName' THEN LName
WHEN 'Email' THEN Email
WHEN 'City' THEN City
ELSE ''
END DESC),
EmpID,FName AS FirstName, LName AS LastName, Email, City, DOB as 'Date-Of-Birth'
FROM EmpData
)
SELECT
*
FROM CTE
ORDER BY CASE #SortDirection WHEN 'DESC' THEN Seq2 ELSE Seq1 END
DEMO
It is better to use dynamic SQL in such cases
Declare #sql nvarchar(max)
declare #orderby nvarchar(100) = ' ORDER BY '
DECLARE #SortByColumn varchar(20) = 'City'
declare #SortDirection varchar(5) = 'ASC'
set #sql = '
SELECT EmpID,FName AS FirstName, LName AS LastName, Email, City, DOB as ''Date-Of-Birth''
FROM EmpData
' +
CASE #SortByColumn
WHEN 'FirstName' THEN #orderby + ' FName ' + #SortDirection
WHEN 'LastName' THEN #orderby + ' LName ' + #SortDirection
WHEN 'Email' THEN #orderby + ' Email ' + #SortDirection
WHEN 'City' THEN #orderby + ' City ' + #SortDirection
ELSE ''
END
exec sp_executesql #sql
Since ASC or DESC is SQL clauses, we can not use them in CASE statements

SQL ORDER BY query

I want to have my table,rcarddet, ordered by "SDNO" (not primary key) in ascending order with the exception of "0". So it should turn out to be like:
1
1
2
.
.
10
0
0
My query now is:
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
AND `SDNO` != 0
ORDER BY `rcarddet`.`SDNO` ASC;
The easiest way
SELECT * FROM rcarddet
WHERE RDATE = '2011-05-25' and RCNO = '1'and PLACE = 'H'
ORDER BY CASE
WHEN rcarddet.SDNO = 0 THEN [max_number_for_the_type_of_SDNO]
ELSE rcarddet.SDNO
END ASC
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
ORDER BY
`SDNO` = 0,
`SDNO`;