选择两列之间的最近日期

时间:2009-01-05 19:33:00

标签: sql database sql-server-2005

如果我有一个表(在其他列中)有两个DATETIME列,我如何从这两列中选择最近日期。

示例:

ID     Date1     Date2

1      1/1/2008   2/1/2008

2      2/1/2008   1/1/2008

3      1/10/2008  1/10/2008

如果我希望我的结果看起来像

ID     MostRecentDate

1      2/1/2008

2      2/1/2008

3      1/10/2008

有一种简单的方法可以做到这一点,我显然是在忽视吗?我知道我可以做子查询和case语句,甚至可以在sql server中编写一个函数来处理它,但我脑子里已经知道有一个已经内置的max-compare类型函数,我只是忘记了。

13 个答案:

答案 0 :(得分:38)

CASE是恕我直言的最佳选择:

SELECT ID,
       CASE WHEN Date1 > Date2 THEN Date1
            ELSE Date2
       END AS MostRecentDate
FROM Table

如果其中一列可以为空,则需要将其括在COALESCE中:

.. COALESCE(Date1, '1/1/1973') > COALESCE(Date2, '1/1/1973')

答案 1 :(得分:5)

select ID, 
case
when Date1 > Date2 then Date1
else Date2
end as MostRecentDate
from MyTable

答案 2 :(得分:5)

您可以将其抛入标量函数,这使得处理空值更容易一些。显然它不会比内联案例陈述更快。

ALTER FUNCTION [fnGetMaxDateTime] (
    @dtDate1        DATETIME,
    @dtDate2        DATETIME
) RETURNS DATETIME AS
BEGIN
    DECLARE @dtReturn DATETIME;

    -- If either are NULL, then return NULL as cannot be determined.
    IF (@dtDate1 IS NULL) OR (@dtDate2 IS NULL)
        SET @dtReturn = NULL;

    IF (@dtDate1 > @dtDate2)
        SET @dtReturn = @dtDate1;
    ELSE
        SET @dtReturn = @dtDate2;

    RETURN @dtReturn;
END

答案 3 :(得分:2)

尽可能使用InLine函数,因为它们不会遇到通常与UDF相关的性能问题......

Create FUNCTION MaximumDate 
(   
@DateTime1 DateTime,
@DateTime2 DateTime
)
RETURNS TABLE 
AS
RETURN 
(
    Select Case When @DateTime1 > @DateTime2 Then @DateTime1
                Else @DateTime2 End MaxDate
)
GO 

有关使用指南,请参阅Here

答案 4 :(得分:2)

我认为接受的答案是最简单的。但是,我会在日期中查看空值...

SELECT ID,
       CASE WHEN ISNULL(Date1,'01-01-1753') > ISNULL(Date2,'01-01-1753') THEN Date1
            ELSE Date2
       END AS MostRecentDate
FROM Table

答案 5 :(得分:2)

SQL Server 2012 ,可以使用快捷方式IIFCASE表达式,尽管后者是SQL标准:

SELECT ID,
       IIF(DateColA > DateColB, DateColA, DateColB) AS MostRecentDate
  FROM theTable

答案 6 :(得分:1)

除了个案陈述,我不相信......

  Select Case When DateColA > DateColB Then DateColA 
              Else DateColB End MostRecent
  From Table ... 

答案 7 :(得分:0)

AFAIK,没有内置函数可以获得最多两个值,但您可以轻松编写自己的函数:

CREATE FUNCTION dbo.GetMaximumDate(@date1 DATETIME, @date2 DATETIME)
RETURNS DATETIME
AS
BEGIN
    IF (@date1 > @date2)
        RETURN @date1
    RETURN @date2
END

并将其命名为

SELECT Id, dbo.GetMaximumDate(Date1, Date2)
FROM tableName

答案 8 :(得分:0)

This thread有几个解决方案。如果您有两个以上的日期进行比较,“unpivot”可能比编写一系列案例陈述更可取。以下是Niikola

的公然被盗
select id, max(dDate) MostRecentDate
  from YourTable
    unpivot (dDate for nDate in (Date1, Date2, Date3)) as u
  group by id 

然后你可以order by dDate,如果这有用的话。

答案 9 :(得分:0)

已发布的所有其他正确答案。

但如果您仍然在寻找MAX关键字,那么这是一种方式:

select ID , MAX(dt) from 
(  select Id , Date1 as dt from table1
   union  
   select ID , Date2 from table2
) d
group by d.Id

答案 10 :(得分:0)

select max(d) ChangeDate
from (values(@d), (@d2)) as t(d)

答案 11 :(得分:0)

from functools import partial
from concurrent.futures import ThreadPoolExecutor

class Test(object):
    def process_dataframe(self, id):
        print(id*id)

    def run_task(self):
        functions = []
        for i in range(1,10): 
            functions.append(partial(self.process_dataframe, i))
        self.run_functions_in_parallel(functions)

    def run_functions_in_parallel(self, functions, max_workers=8):
        executor = ThreadPoolExecutor(max_workers=max_workers)
        futures = [
            executor.submit(function)
            for function in functions
        ]

        errors = []
        results = []
        for future in futures:
            try:
                result = future.result()
            except Exception as e:
                errors.append(e)
            else:
                results.append(result)
        if errors:
            raise Exception(errors)
        return results

d = Test()
d.run_task()

答案 12 :(得分:-1)

为什么你不能使用GREATEST功能?

select id, date1, date2, GREATEST( nvl(date1,date2) , nvl(date2, date1) )
from table1;

我包含一个NVL以确保正确评估NULL,否则如果Date1或Date2为null,则Greatest返回NULL。

ID  Date1       Date2       MostRecentDate
1   1/1/2008    2/1/2008    2/1/2008
2   2/1/2008    1/1/2008    2/1/2008
3   1/10/2008   1/10/2008   1/10/2008
4   -null-      2/10/2008   2/10/2008
5   2/10/2008   -null-      2/10/2008