我有一个表,我正在存储时间跨度数据。该表的架构类似于:
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
答案 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修改为MAX
答案 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
但我不知道联盟是否会对表现产生重大影响