代码之家  ›  专栏  ›  技术社区  ›  Ross

在SQL中选择最小日期或空值

  •  2
  • Ross  · 技术社区  · 6 年前

    我有一张桌子,大致如下:

    CREATE TABLE Table1
        ([ID] int, [USER] varchar(5), [DATE] date)
    ;
    
    INSERT INTO Table1
        ([ID], [USER], [DATE])
    VALUES
        (1, 'A', '2018-10-01'),
        (2, 'A', '2018-09-01'),
        (3, 'A', NULL),
        (4, 'B', '2018-05-03'),
        (5, 'B', '2017-04-01'),
        (6, 'C', NULL)
    ;
    

    DATE 变量最小。

    SELECT T.USER FROM TABLE1 T
    WHERE T.DATE = (SELECT MIN(DATE) FROM TABLE1 T1 WHERE T1.USER = T.USER)
    

    工作得很好,但是在实例中没有填充 字段,将有一行 NULL ,就像我上面表格的最后一行,我也希望选择它。

    (2, 'A', '2018-09-01'),
    (5, 'B', '2017-04-01'),
    (6, 'C', NULL)
    

    SQL小提琴: http://www.sqlfiddle.com/#!9/df42b5/6

    我认为可以使用EXCLUDE语句来做一些事情,但是它很快就会变得复杂。

    4 回复  |  直到 6 年前
        1
  •  2
  •   Fahmi    6 年前

    您可以尝试使用行号()

    demo

        select * from
        (select *, row_number() over(partition by [user] order by [user],case when 
         [date] is null then 0 else 1 end desc,[date]) as rn
         from Table1)x where rn=1
    
        2
  •  1
  •   Zaynul Abadin Tuhin    6 年前

    使用union和co相关子查询 min()

         CREATE TABLE Table1 (ID int, usr varchar(50), DATE1 date)
    ;
    
    INSERT INTO Table1 VALUES
        (1, 'A', '2018-10-01'),
        (2, 'A', '2018-09-01'),
        (3, 'A', NULL),
        (4, 'B', '2018-05-03'),
        (5, 'B', '2017-04-01'),
        (6, 'C', NULL)
    ;
    
    
    
    select * from Table1 t  where 
       DATE1= (select min(date1) from Table1 t1 where t1.usr=t.usr
             ) and date1 is not null
               union
    select * from Table1 t where date1 is  null
    and t.usr not in ( select usr from Table1 where date1 is not null)
    

    DEMO

    ID  usr     DATE1
    2   A   01/09/2018 00:00:00
    5   B   01/04/2017 00:00:00
    6   C   
    
        3
  •  0
  •   Sorin G    6 年前

    select t.Id
        , x.[User]
        , x.[MinDate] as [Date]
    from
    (select [User]
       , min([Date]) as MinDate
    from table1
    group by [User]) x
       inner join table1 t on t.[User] = x.[User] and (t.[Date] = x.[MinDate] or x.[MinDate] is null)
    
        4
  •  0
  •   Vladislav    6 年前

    ;WITH chronology AS (
        SELECT 
            *,
            ROW_NUMBER() OVER (
                PARTITION BY [USER] 
                ORDER BY ISNULL([DATE], '2900-01-01') ASC
            ) Idx
        FROM TABLE1
    )
    SELECT ID, [USER], [DATE]  
    FROM chronology
    WHERE Idx=1;
    

    在这个解决方案中使用CTE简化了查询,提高了其可读性、可维护性和可扩展性。此外,我希望这种方法在性能方面是最佳的。