SQL Server 2012:含指定日期时获取列中次小日期的查询问题
没问题,我来帮你搞定这个SQL Server 2012的日期筛选需求!首先咱们先把表和测试数据准备好,再一步步实现你要的逻辑。
解决方案:SQL Server 2012 按规则获取行内最小日期
首先创建表并插入测试数据:
-- 创建表t CREATE TABLE t ( dt1 date, dt2 date, dt3 date, dt4 date ); -- 插入测试数据 INSERT INTO t VALUES ('1970-01-01','2008-10-10',NULL,NULL), (NULL,'2008-10-10','2017-10-12',NULL), ('1970-01-01','2008-10-10',NULL,'2018-10-09');
核心思路
你的需求是对每行的四个日期列,获取最小日期;但如果该行存在'1970-01-01',则排除这个值后取最小(也就是第二小的日期)。直接对列操作会比较繁琐,我们可以先把每行的多个日期列转换为多行(行转列),这样就能更灵活地筛选和排序日期。
实现方案(推荐)
这里用CROSS APPLY实现行转列,结合聚合函数和条件判断来得到目标日期:
SELECT -- 保留原表所有列 t.dt1, t.dt2, t.dt3, t.dt4, -- 根据规则计算目标日期 CASE -- 判断当前行是否存在'1970-01-01' WHEN MAX(CASE WHEN ud.dt = '1970-01-01' THEN 1 ELSE 0 END) = 1 -- 存在则排除该值后取最小日期 THEN MIN(CASE WHEN ud.dt <> '1970-01-01' THEN ud.dt END) -- 不存在则直接取最小日期 ELSE MIN(ud.dt) END AS target_min_date FROM t -- 将四个日期列转为多行,同时过滤NULL值 CROSS APPLY ( VALUES (dt1), (dt2), (dt3), (dt4) ) unpivoted_dates(dt) WHERE unpivoted_dates.dt IS NOT NULL -- 按原表的行分组 GROUP BY t.dt1, t.dt2, t.dt3, t.dt4;
方案解释
- 行转列:通过
CROSS APPLY配合VALUES,把每行的四个日期列拆成单独的行,同时用WHERE过滤掉NULL值,避免干扰计算。 - 条件判断:用
MAX(CASE...)判断当前行是否包含'1970-01-01'——如果存在,这个值会返回1,否则0。 - 计算目标日期:如果存在'1970-01-01',就用
MIN(CASE...)排除该值后取最小日期;否则直接取所有日期的最小值。
测试结果
执行上面的SQL后,会得到如下结果:
| dt1 | dt2 | dt3 | dt4 | target_min_date |
|---|---|---|---|---|
| 1970-01-01 | 2008-10-10 | NULL | NULL | 2008-10-10 |
| NULL | 2008-10-10 | 2017-10-12 | NULL | 2008-10-10 |
| 1970-01-01 | 2008-10-10 | NULL | 2018-10-09 | 2008-10-10 |
完全符合你的需求:第一行和第三行因为存在'1970-01-01',取了第二小的日期;第二行没有该值,直接取最小日期。
内容的提问来源于stack exchange,提问作者GI.JOE
相关产品推荐
相关产品推荐

