Sort by minimum value of two columns

后端 未结 13 1204
暖寄归人
暖寄归人 2021-02-03 17:13

I use SQL Server 2008 R2.

I need to sort a table by the minimal value of two columns.

The table looks like this:

ID: integer; 
Date         


        
相关标签:
13条回答
  • 2021-02-03 17:46

    The simplest way is using of the VALUES keyword, like the following:

    SELECT ID, Date1, Date2
    FROM YourTable
    ORDER BY (SELECT MIN(v) FROM (VALUES (Date1), (Date2)) AS value(v))
    

    This code will work for all the cases, even with nullable columns.

    Edit :

    The solution with the COALESCE keyword is not universal. It has the important restrictions:

    • It won't work if the columns are of the Date type (if you use the dates before 01/01/1753)
    • It won't work in case one of the columns is NULL. It interprets the NULL value as the minimal datetime value. But is it actually true? It isn't even datetime, it is nothing.
    • The IF expression will be much more complicated if we use more than two columns.

    According to the question:

    What is the simplest way to sort this table that way?

    The shortest and the simplest solution is the one which described above, because:

    • It doesn't take a lot of coding to implement it - simply add an one more line.
    • You don't need to care about whether the columns are nullable or not. You just use the code and it works.
    • You can extend the number of columns in your query simply by adding the one after a comma.
    • It works with the Date columns and you don't need to modify the code.

    Edit 2 :

    Zohar Peled suggested the following way of order:

    I would order the rows by this rules: first, when both null, second, when date1 is null, third, when date 2 is null, fourth, min(date1, date2)

    So, for this case the solution can be reached by using of the same approach, like the following:

    SELECT ID, Date1, Date2
    FROM YourTable
    ORDER BY 
    CASE WHEN Date1 IS NULL AND Date2 IS NULL THEN 0
         WHEN Date1 IS NULL THEN 1
         WHEN Date2 IS NULL THEN 2
         ELSE 3 END,
    (SELECT MIN(v) FROM (VALUES ([Date1]), ([Date2])) AS value(v))
    

    The output for this code is below:

    The output result for *Zohar's* way of order

    The COALESCE solution will not sort the table this way. It messes up the rows where at least one cell of the NULL value. The output of it is the following:

    Weird ORDER BY of <code>COALESCE</code> solution

    Hope this helps and waiting for critics.

    0 讨论(0)
  • 2021-02-03 17:47

    I would order the rows by this rules:

    1. when both null
    2. when date1 is null
    3. when date 2 is null
    4. min(date1, date2)

    To do this a nested case will be simple and efficient (unless the table is very large) according to this post.

    SELECT ID, Date1, Date2
    FROM YourTable
    ORDER BY 
    CASE 
      WHEN Date1 IS NULL AND Date2 IS NULL THEN 0
      WHEN Date1 IS NULL THEN 1
      WHEN Date2 IS NULL THEN 2
      ELSE 3 END,
    CASE 
      WHEN Date1 < Date2 THEN Date1
      ELSE Date2
    END
    
    0 讨论(0)
  • 2021-02-03 17:49

    I prefer this way to handle nullable columns:

    SELECT Id, Date1, Date2
    FROM YourTable
    ORDER BY 
       CASE 
         WHEN Date1 < Date2 OR Date1 IS NULL THEN Date1 
         ELSE Date2 
       END 
    
    0 讨论(0)
  • 2021-02-03 17:49

    There's an another option. You can calculate the result column by needed logic and cover the select by external one with ordering by your column. In this case the code will be the following:

    select ID, x.Date1, x.Date2
    from
    (
        select
            ID,
            Date1,
            Date2, 
            SortColumn = case when Date1 < Date2 then Date1 else Date2 end
        from YourTable
    ) x
    order by x.SortColumn
    

    The benefit of this solution is that you can add necessary filtering queries (in the inner select) and still the indexes will be useful.

    0 讨论(0)
  • 2021-02-03 17:52

    I think when you want to sort on both fields of date1 and date2, you should have both of them in the ORDER BY part, like this:

    SELECT *
    FROM aTable
    ORDER BY 
        CASE WHEN date1 < date2 THEN date1 
        ELSE date2 END, 
        CASE WHEN date1 < date2 THEN date2 
        ELSE date1 END
    

    Result can be like this:

    date1      | date2      
    -----------+------------
    2015-04-25 | 2015-04-21
    2015-04-26 | 2015-04-21
    2015-04-25 | 2015-04-22
    2015-04-22 | 2015-04-26
    

    To have a prefect result with Null values use:

    SELECT *
    FROM aTable
    ORDER BY 
        CASE 
            WHEN date1 IS NULL THEN NULL
            WHEN date1 < date2 THEN date1 
        ELSE date2 END 
        ,CASE 
            WHEN date2 IS NULL THEN date1
            WHEN date1 IS NULL THEN date2
            WHEN date1 < date2 THEN date2 
        ELSE date1 END
    

    Results will be like this:

    date1      | date2      
    -----------+------------
    NULL       | NULL
    NULL       | 2015-04-22
    2015-04-26 | NULL
    2015-04-25 | 2015-04-21
    2015-04-26 | 2015-04-21
    2015-04-25 | 2015-04-22
    
    0 讨论(0)
  • 2021-02-03 17:53

    If you don't want to use Case statement in the Order By , then this is another approach, just moving the Case statement to Select

    SELECT Id, Date1, Date2 FROM 
     (SELECT Id, Date1, Date2
      ,CASE WHEN Date1 < Date2 THEN Date1 ELSE Date2 END as MinDate 
    FROM YourTable) as T
    ORDER BY MinDate
    
    0 讨论(0)
提交回复
热议问题