Sorting multiple columns in various sort directions in a case statement

  • 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.

  • Can you post a more complete statement so it's clearer what you're doing?

  • 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?

  • 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

  • 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. 🙁

  • 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

  • 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/

  • 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.

    “Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    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

  • 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.

  • 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?

    “Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    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

  • 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.

  • 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.

  • 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.

  • 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