September 27, 2012 at 7:45 am
Hello all,
I am trying to implement server side processing for jQuery DataTables so I need to be able to sort multiple columns in different directions using a case statement and I am having some difficulty. I would really like to do this without using dynamic SQL.
I know I can sort on multiple columns in the same direction using something like:
CASE @SortColumn WHEN 'NameAsc' THEN LastName + ', ' + FirstName END ASC,
but what if I want the LastName sorted DESC and the FirstName sorted ASC, how do I do that?
Thank in advance for your help.
September 27, 2012 at 8:40 am
Can you post a more complete statement so it's clearer what you're doing?
September 27, 2012 at 8:57 am
Sure. Here is what I have currently which works fine for single columns sorts.
BEGIN
insert into #QualifyingStreets
(
RowNum,
StreetName,
AddFrom,
AddTo,
Maintainer,
LCity,
RCity,
LZipCode,
RZipCode,
StrAltName,
Location,
CntyName,
SegLength
)
select Row_Number() OVER(ORDER BY
CASE @SortColumn WHEN 'StreetNameAsc' THEN StreetName END ASC,
CASE @SortColumn WHEN 'StreetNameDesc' THEN StreetName END DESC,
CASE @SortColumn WHEN 'AddFromAsc' THEN AddFrom END ASC,
CASE @SortColumn WHEN 'AddFromDesc' THEN AddFrom END DESC,
CASE @SortColumn WHEN 'AddToAsc' THEN AddTo END ASC,
CASE @SortColumn WHEN 'AddToDesc' THEN AddTo END DESC,
CASE @SortColumn WHEN 'MaintainerAsc' THEN Maintainer END ASC,
CASE @SortColumn WHEN 'MaintainerDesc' THEN Maintainer END DESC,
CASE @SortColumn WHEN 'LCityAsc' THEN LCity END ASC,
CASE @SortColumn WHEN 'LCityDesc' THEN LCity END DESC,
CASE @SortColumn WHEN 'RCityAsc' THEN RCity END ASC,
CASE @SortColumn WHEN 'RCityDesc' THEN RCity END DESC,
CASE @SortColumn WHEN 'LZipCodeAsc' THEN LZipCode END ASC,
CASE @SortColumn WHEN 'LZipCodeDesc' THEN LZipCode END DESC,
CASE @SortColumn WHEN 'RZipCodeAsc' THEN RZipCode END ASC,
CASE @SortColumn WHEN 'RZipCodeDesc' THEN RZipCode END DESC,
CASE @SortColumn WHEN 'StrAltNameAsc' THEN StrAltName END ASC,
CASE @SortColumn WHEN 'StrAltNameDesc' THEN StrAltName END DESC,
CASE @SortColumn WHEN 'LocationAsc' THEN Location END ASC,
CASE @SortColumn WHEN 'LocationDesc' THEN Location END DESC,
CASE @SortColumn WHEN 'CntyNameAsc' THEN CntyName END ASC,
CASE @SortColumn WHEN 'CntyNameDesc' THEN CntyName END DESC,
CASE @SortColumn WHEN 'SegLengthAsc' THEN SegLength END ASC,
CASE @SortColumn WHEN 'SegLengthDesc' THEN SegLength END DESC,
StreetName ASC)
as RowNum,
StreetName,
AddFrom,
AddTo,
Maintainer,
LCity,
RCity,
LZipCode,
RZipCode,
StrAltName,
Location,
CntyName,
SegLength
from tblGISStreetIndex
where
StreetName like @StreetName + '%'
END
I can get the multi columns with the same sort direction using this:
CASE @SortColumn WHEN 'StreetName' THEN Maintainer + ', ' + StreetName END ASC,
but how could I do something like sorting by Maintainer ASC and StreetName DESC?
September 27, 2012 at 9:30 am
How about adding 2 rows to the ORDER BY statement? See 'Example'.
--================ TEST DATA ==========================
if object_id('dbo.tblGISStreetIndex') is not null
drop table dbo.tblGISStreetIndex;
create table dbo.tblGISStreetIndex
(
FirstName Varchar(40),
LastName Varchar(40),
StreetName Varchar(40),
AddFrom Varchar(40),
AddTo Varchar(40),
Maintainer Varchar(40),
LCity Varchar(40),
RCity Varchar(40),
LZipCode Varchar(40),
RZipCode Varchar(40),
StrAltName Varchar(40),
Location Varchar(40),
CntyName Varchar(40),
SegLength int
);
insert dbo.tblGISStreetIndex (FirstName, LastName, StreetName) values ( 'Doug', 'Carroll', 'High Street' );
insert dbo.tblGISStreetIndex (FirstName, LastName, StreetName) values ( 'Harry', 'Carroll', 'High Street' );
insert dbo.tblGISStreetIndex (FirstName, LastName, StreetName) values ( 'Edgar', 'Carroll', 'High Street' );
insert dbo.tblGISStreetIndex (FirstName, LastName, StreetName) values ( 'Edgar', 'Carroll', 'High Road' );
insert dbo.tblGISStreetIndex (FirstName, LastName, StreetName) values ( 'Edgar', 'Carroll', 'High Lane' );
insert dbo.tblGISStreetIndex (FirstName, LastName, StreetName) values ( 'Bill', 'Carroll', 'High Street' );
insert dbo.tblGISStreetIndex (FirstName, LastName, StreetName) values ( 'Alex', 'Arnold', 'High Town' );
insert dbo.tblGISStreetIndex (FirstName, LastName, StreetName) values ( 'Charlie', 'Bailey', 'Higher Moors' );
insert dbo.tblGISStreetIndex (FirstName, LastName, StreetName) values ( 'Sam', 'Smith', 'Low Hovels' );
--select * from dbo.tblGISStreetIndex;
--=============== PROCEDURE ==========================
DECLARE @SortColumn Varchar(20);
SET @SortColumn = 'Example';
DECLARE @StreetName Varchar(40);
SET @StreetName = 'High';
BEGIN
-- insert into #QualifyingStreets
-- (
-- RowNum,
-- StreetName,
-- AddFrom,
-- AddTo,
-- Maintainer,
-- LCity,
-- RCity,
-- LZipCode,
-- RZipCode,
-- StrAltName,
-- Location,
-- CntyName,
-- SegLength
--)
select Row_Number() OVER(ORDER BY
CASE @SortColumn WHEN 'StreetNameAsc' THEN StreetName END ASC,
CASE @SortColumn WHEN 'StreetNameDesc' THEN StreetName END DESC,
CASE @SortColumn WHEN 'AddFromAsc' THEN AddFrom END ASC,
CASE @SortColumn WHEN 'AddFromDesc' THEN AddFrom END DESC,
CASE @SortColumn WHEN 'AddToAsc' THEN AddTo END ASC,
CASE @SortColumn WHEN 'AddToDesc' THEN AddTo END DESC,
CASE @SortColumn WHEN 'MaintainerAsc' THEN Maintainer END ASC,
CASE @SortColumn WHEN 'MaintainerDesc' THEN Maintainer END DESC,
CASE @SortColumn WHEN 'LCityAsc' THEN LCity END ASC,
CASE @SortColumn WHEN 'LCityDesc' THEN LCity END DESC,
CASE @SortColumn WHEN 'RCityAsc' THEN RCity END ASC,
CASE @SortColumn WHEN 'RCityDesc' THEN RCity END DESC,
CASE @SortColumn WHEN 'LZipCodeAsc' THEN LZipCode END ASC,
CASE @SortColumn WHEN 'LZipCodeDesc' THEN LZipCode END DESC,
CASE @SortColumn WHEN 'RZipCodeAsc' THEN RZipCode END ASC,
CASE @SortColumn WHEN 'RZipCodeDesc' THEN RZipCode END DESC,
CASE @SortColumn WHEN 'StrAltNameAsc' THEN StrAltName END ASC,
CASE @SortColumn WHEN 'StrAltNameDesc' THEN StrAltName END DESC,
CASE @SortColumn WHEN 'LocationAsc' THEN Location END ASC,
CASE @SortColumn WHEN 'LocationDesc' THEN Location END DESC,
CASE @SortColumn WHEN 'CntyNameAsc' THEN CntyName END ASC,
CASE @SortColumn WHEN 'CntyNameDesc' THEN CntyName END DESC,
CASE @SortColumn WHEN 'SegLengthAsc' THEN SegLength END ASC,
CASE @SortColumn WHEN 'SegLengthDesc' THEN SegLength END DESC,
CASE @SortColumn WHEN 'NameAsc' THEN LastName + ', ' + FirstName END ASC,
CASE @SortColumn WHEN 'Example' THEN LastName END DESC,
CASE @SortColumn WHEN 'Example' THEN FirstName END ASC,
StreetName ASC)
as RowNum,
FirstName,
LastName,
StreetName,
AddFrom,
AddTo,
Maintainer,
LCity,
RCity,
LZipCode,
RZipCode,
StrAltName,
Location,
CntyName,
SegLength
from tblGISStreetIndex
where
StreetName like @StreetName + '%'
END
September 27, 2012 at 11:54 am
That looks like that will probably work, however I have 12 columns, any 1 or more can be selected for sorting in any order and each one in either direction. That will make for one huge case statement to cover every possible combination. 🙁
September 27, 2012 at 12:01 pm
Is there a front-end? If so that is where I would put the sorting logic.
If not, or you must do this in the database, you could look into using sp_executesql with parameters.
There are no special teachers of virtue, because virtue is taught by the whole community.
--Plato
September 27, 2012 at 12:13 pm
Take a look at this article by Gail about catch-all queries. Your situation is not exactly the same but you can modify the logic presented to handle your complicated sorting requirements.
http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/[/url]
If at all possible with opc.three to leave this sorting in the application. It will be far easier to do this there.
_______________________________________________________________
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 Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.
Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/
September 28, 2012 at 1:56 am
Barry Couch (9/27/2012)
CASE @SortColumn WHEN 'StreetName' THEN Maintainer + ', ' + StreetName END ASC,
but how could I do something like sorting by Maintainer ASC and StreetName DESC?
You will need more than one variable. Alternatively, pack @SortColumn with a list of the keywords you're using - 'Maintainer ASC,StreetName DESC' and resolve into a temp table using a splitter to give
Column Direction
-------- ----------
Maintainer ASC
StreetName DESC
There's quite a bit of coding involved.
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
September 28, 2012 at 5:32 am
opc.three (9/27/2012)
Is there a front-end? If so that is where I would put the sorting logic.If not, or you must do this in the database, you could look into using sp_executesql with parameters.
Thank you for your response. There is a front-end, however I am only returning a subset of the data so I can't sort it in the front-end, it has to be sorted before I grab the subset. For instance, if they enter "F" in the search box it will return all streets that begin with the letter "F". The default number of records to display is 10. If there are 30 streets that begin with "F" and it is sorted by streetname then I will pull the first 10 ordered by streetname. If they page to the next screen then I will grab the next 10, etc.
September 28, 2012 at 5:36 am
Barry Couch (9/28/2012)
opc.three (9/27/2012)
Is there a front-end? If so that is where I would put the sorting logic.If not, or you must do this in the database, you could look into using sp_executesql with parameters.
Thank you for your response. There is a front-end, however I am only returning a subset of the data so I can't sort it in the front-end, it has to be sorted before I grab the subset. For instance, if they enter "F" in the search box it will return all streets that begin with the letter "F". The default number of records to display is 10. If there are 30 streets that begin with "F" and it is sorted by streetname then I will pull the first 10 ordered by streetname. If they page to the next screen then I will grab the next 10, etc.
How does this allow you to sort by multiple columns?
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
September 28, 2012 at 5:37 am
Sean Lange (9/27/2012)
Take a look at this article by Gail about catch-all queries. Your situation is not exactly the same but you can modify the logic presented to handle your complicated sorting requirements.http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/[/url]
Thank you for your response. That article is using dynamic SQL which I am hoping to avoid. However, I may have no choice in this case.
Sean Lange (9/27/2012)
If at all possible with opc.three to leave this sorting in the application. It will be far easier to do this there.
See my response to opc.three above.
September 28, 2012 at 5:43 am
ChrisM@Work (9/28/2012)
Barry Couch (9/28/2012)
opc.three (9/27/2012)
Is there a front-end? If so that is where I would put the sorting logic.If not, or you must do this in the database, you could look into using sp_executesql with parameters.
Thank you for your response. There is a front-end, however I am only returning a subset of the data so I can't sort it in the front-end, it has to be sorted before I grab the subset. For instance, if they enter "F" in the search box it will return all streets that begin with the letter "F". The default number of records to display is 10. If there are 30 streets that begin with "F" and it is sorted by streetname then I will pull the first 10 ordered by streetname. If they page to the next screen then I will grab the next 10, etc.
How does this allow you to sort by multiple columns?
That itself doesn't. That was just a simplistic example to show why sorting on the front-end will not work in this case. DataTable has the ability to pass parameters that allows for sorting on each column in the DataTable, each in ASC or DESC order. It also allows for filtering on each column but for now I am limiting filtering to just the streetname.
September 28, 2012 at 5:47 am
ChrisM@Work (9/28/2012)
Barry Couch (9/27/2012)
CASE @SortColumn WHEN 'StreetName' THEN Maintainer + ', ' + StreetName END ASC,
but how could I do something like sorting by Maintainer ASC and StreetName DESC?
You will need more than one variable. Alternatively, pack @SortColumn with a list of the keywords you're using - 'Maintainer ASC,StreetName DESC' and resolve into a temp table using a splitter to give
Column Direction
-------- ----------
Maintainer ASC
StreetName DESC
There's quite a bit of coding involved.
Thanks for your response. I am not sure how splitting the values into a temp table is going to help me. I am not having trouble passing or retrieving the values. The problem is with how to construct the case statement to allow for sorting on multiple columns each in either ASc or DESC direction.
September 28, 2012 at 10:26 am
What is the upper bound of your data set size? Sounds like you're in .NET too. Client-side paging with sorting really is best done in memory in the presentation-tier (or a stateful middle-tier if you have one) as long as you can restrict the initial set to a reasonable size. Telerik has some nice grid controls for ASP.NET that I have used in the past that help with this kind of thing.
Things get much easier for us in 2012 with OFFSET added to ORDER BY (selling point for an upgrade ;-)) but you're still in that same boat of having to construct an ORDER BY clause dynamically.
There are no special teachers of virtue, because virtue is taught by the whole community.
--Plato
Viewing 14 posts - 1 through 13 (of 13 total)
You must be logged in to reply to this topic. Login to reply