我有一张看起来更像这样的表:
K_PKEY D_FROM D_TO PERC
============ ==================== ==================== ===========
0013 01-JAN-2009 00:00:00 31-JUL-2011 00:00:00
0013 01-AUG-2011 00:00:00 31-DEC-2011 00:00:00
0013 01-JAN-2012 00:00:00 31-MAR-2012 00:00:00
0013 01-APR-2012 00:00:00 31-DEC-2012 00:00:00 75.000000
0013 01-JAN-2013 00:00:00 31-JAN-2013 00:00:00 50.000000
0013 01-FEB-2013 00:00:00 28-FEB-2013 00:00:00 50.000000
0013 01-MAR-2013 00:00:00 31-AUG-2013 00:00:00 75.000000
0013 01-SEP-2013 00:00:00 31-MAY-2015 00:00:00 75.000000
0013 01-JUN-2015 00:00:00 31-DEC-2100 00:00:00
我正在尝试构建一个考虑特定日期范围的DISTICT查询。
这就是我提出的:
SELECT DISTINCT k_pkey, MIN(d_from), MAX(d_to), perc FROM my_table GROUP BY k_pkey
它没有按照我想要的方式工作,我理解为什么。 MIN()和MAX()结合DISTINCT全局工作,这对于那种类型的查询是很自然的。这导致:
K_PKEY D_FROM D_TO PERC
============ ==================== ==================== ===========
0013 01-JAN-2009 00:00:00 31-DEC-2100 00:00:00
0013 01-APR-2012 00:00:00 31-MAY-2015 00:00:00 75.000000
0013 01-JAN-2013 00:00:00 28-FEB-2013 00:00:00 50.000000
我想要达到的目标是按时间顺序排列并且只将(可以说)彼此相邻的范围组合在一起。
K_PKEY D_FROM D_TO PERC
============ ==================== ==================== ===========
0013 01-JAN-2009 00:00:00 31-MAR-2012 00:00:00
0013 01-APR-2012 00:00:00 31-DEC-2012 00:00:00 75.000000
0013 01-JAN-2013 00:00:00 28-FEB-2013 00:00:00 50.000000
0013 01-MAR-2013 00:00:00 31-MAY-2015 00:00:00 75.000000
0013 01-JUN-2015 00:00:00 31-DEC-2100 00:00:00
是否可以使用一个SQL查询(如果可能,我不想使用sql过程)?有什么建议吗?
答案 0 :(得分:2)
您正尝试将相邻的行组合在一起,基于日期和PERC
相同。我们的想法是使用left join
来确定哪些值开始新的范围。然后,使用累计和来计算每行的启动次数。后一个值可用于分组。
在SQL Server 2012+中,累积总和可以直接完成。在早期版本中,您将使用outer apply
。
生成的查询如下所示:
select k_pkey, min(d_from) as d_from, max(d_to) as d_to, perc
from (select t.*,
sum(IsGroupStart) over (partition by k_pkey, perc order by d_from) as grp
from (select t.*,
(case when t_prev.k_pkey is null then 1 else 0 end) as IsGroupStart
from t left join
t tprev
on tprev.k_pkey = t.k_pkey and
(tprev.perc = t.perc or tprev.perc is null and t.perc is null) and
tprev.d_to = dateadd(day, -1, t.d_from)
) t
) t
group by grp, k_pkey, perc;