如何在MIN或MAX中包含空值?

时间:2014-01-22 14:52:45

标签: sql sql-server tsql

我有一个表,我正在存储时间跨度数据。该表的架构类似于:

ID INT NOT NULL IDENTITY(1,1)   
RecordID INT NOT NULL  
StartDate DATE NOT NULL  
EndDate DATE NULL  

我正在尝试计算每个记录ID的开始和结束日期,因此最小StartDate和最大EndDate。 StartDate不可为空,所以我不需要担心这一点,但我需要MAX(EndDate)来表示这是当前的运行时间。

重要的是我保持EndDate的NULL值并将其视为最大值。

最简单的尝试(下面)并没有突出显示MIN和MAX将忽略NULLS的问题(来源:http://technet.microsoft.com/en-us/library/ms179916.aspx)。

SELECT recordid, MIN(startdate), MAX(enddate) FROM tmp GROUP BY recordid

我已经创建了一个基本设置的SQL小提琴。

http://sqlfiddle.com/#!3/b0a75

如何根据我的意愿弯曲SQL Server 2008以从SQLFiddle中提供的数据产生以下结果?

RecordId  Start       End  
1         2009-06-19  NULL
2         2012-05-06  NULL
3         2013-01-25  NULL
4         2004-05-06  2009-12-01

6 个答案:

答案 0 :(得分:59)

这有点难看,但因为NULL对你有特殊的意义,这是我能想到的最干净的方法:

SELECT recordid, MIN(startdate),
   CASE WHEN MAX(CASE WHEN enddate IS NULL THEN 1 ELSE 0 END) = 0
        THEN MAX(enddate)
   END
FROM tmp GROUP BY recordid

也就是说,如果任何行都有NULL,我们希望强制它成为答案。只有当没有行包含NULL时,我们才会返回MIN(或MAX)。

答案 1 :(得分:14)

在我的表达中 - count(enddate)计算enddates不为null的行数 count(*)计算总行数 通过比较,您可以轻松判断任何enddates是否包含null。如果它们相同则结果是max(enddate)。否则,该情况将默认返回null,这也是答案。这是一种非常流行的方式来进行这种精确检查。

SELECT recordid, 
MIN(startdate), 
case when count(enddate) = count(*) then max(enddate) end
FROM tmp 
GROUP BY recordid

答案 2 :(得分:3)

使用IsNull

SELECT recordid, MIN(startdate), MAX(IsNull(enddate, Getdate()))
FROM tmp 
GROUP BY recordid

我在第二条指令中将MIN修改为MA​​X

答案 3 :(得分:1)

假设您在给定RecordID的EndDate列中只有一条带null的记录, 这样的东西应该给你想要的输出:

WITH cte1 AS
(
SELECT recordid, MIN(startdate) as min_start , MAX(enddate) as max_end
FROM tmp 
GROUP BY recordid
)

SELECT a.recordid, a.min_start , 
CASE 
   WHEN b.recordid IS  NULL THEN a.max_end
END as max_end
FROM cte1 a
LEFT JOIN tmp b ON (b.recordid = a.recordid AND b.enddate IS NULL)

答案 4 :(得分:0)

使用分析函数:

select case when 
    max(field) keep (dense_rank first order by datfin desc nulls first) is null then 1 
    else 0 end as flag 
from MYTABLE;

答案 5 :(得分:-1)

我尝试使用联合组合两个查询来格式化您想要的回报:

SELECT recordid, startdate, enddate FROM tmp Where enddate is null UNION SELECT recordid, MIN(startdate), MAX(enddate) FROM tmp GROUP BY recordid

但我不知道联盟是否会对表现产生重大影响