如何查询几个可能空白的日期字段的最早日期?

问题描述:

假设表格如下:如何查询几个可能空白的日期字段的最早日期?

+----+----------+-----------+----------+ 
| ID | date1 | date2 | date3 | 
+----+----------+-----------+----------+ 
| 1 | 3/2/2013 | 5/6/2013 |   | 
| 2 |   | 12/1/2011 | 6/5/2010 | 
| 3 | 1/1/1936 | 1/5/1936 | 1/9/1945 | 
| 4 | 2/1/2014 |   |   | 
+----+----------+-----------+----------+ 

我想返回各行的最早日期的查询。至少有一个日期列将被填充。

我已经试过:

SELECT id, 
iif(date1<date2 and date1<date3, 
    date1, 
    iif(date2<date1 and date2<date3, 
     date2, 
     date3)) as dateEarliest 
FROM tbl; 

但似乎如果date3是最早这只返回正确的结果;否则它返回一个空白。

+1

当涉及NULL时,MS Access如何处理' user2246674 2013-05-02 19:19:27

您无法与NULL值进行比较。使用Nz函数将NULL转换为您可以比较的值。 Nz的语法是:Nz (variant, [ value_if_null ])

所以你使用这样的:

iif(Nz(date1,#1/1/2999#) < Nz(date2,#1/1/2999#) and Nz(date1,#1/1/2999#) < (Nz(date3,#1/1/2999#) 

如果这是在Access中使用,你知道VBA,你还可以创建返回所需的值的函数。这可能会更整洁,因为它看起来像:

Select id, LowDate([date1],[date2],[date3]) as dateEarliest 

这是一个函数,应该为你工作。

Function LowDate(D1, D2, D3) 
    D1 = Nz(D1, #1/1/2999#) 
    D2 = Nz(D2, #1/1/2999#) 
    D3 = Nz(D3, #1/1/2999#) 
    If D1 < D2 And D1 < D3 Then 
     LowDate = D1 
    ElseIf D2 < D1 And D2 < D3 Then 
     LowDate = D2 
    Else 
     LowDate = D3 
    End If 
End Function 
+0

+1但是,这个答案似乎意味着'Nz()'总是返回一个字符串,这是一个误导。 – HansUp 2013-05-03 00:29:17

+0

我的第一个答案在null上返回了一个日期,但在我的快速测试中,它不喜欢Nz([date1],#1/1/2099#),所以我改变了我的答案。但在再次测试中,我发现它很有用。之前必须有错别字。 – 2013-05-03 00:52:22

+0

我希望你的答案更多没有所有'CDates',但这是一个小问题,并不足以阻止我的upvote。我担心的是,第一段可能被误解为“Nz()只返回字符串”。 – HansUp 2013-05-03 01:21:26

这可能不是“最好”的方式做到这一点,但要做到这将是逆转置数据的一种方式,所以它看起来是这样的:

id date 
1 
1 3/2/2013 
1 5/6/2013 
2 
2 6/5/2010 
2 12/1/2011 
3 1/1/1936 
3 1/5/1936 
3 1/9/1945 
4 
4 2/1/2014 

这可以像做所以:

SELECT id, date1 from tbl 
UNION 
SELECT id, date2 as date1 from tbl 
UNION 
SELECT id, date3 as date1 from tbl 

(注意:我命名日期字段日期1,因为日期是保留关键字。)

从这里,你可以使用集合功能,如分:

select id, min(date1) as dateEarliest 
from (SELECT id, date1 from tbl 
UNION 
SELECT id, date2 as date1 from tbl 
UNION 
SELECT id, date3 as date1 from tbl) unpivottbl 
group by id; 

哪个会给你你想要的。

我想你可以修改iif声明是这样的:

SELECT id, 
iif((date1<date2 and date1<date3) or (date1 < date2 and date3 is null) or (date1 < date3 and date2 is null), 
    date1, 
    iif(date2<date1 and date2<date3) or (date2 < date1 and date3 is null) or (date2 < date3 and date2 is null), 
     date2, 
     date3)) as dateEarliest 
FROM tbl; 

此,如果您的空白是NULL会工作。