如何在最小和最大日期创建 GROUP BY

Posted

技术标签:

【中文标题】如何在最小和最大日期创建 GROUP BY【英文标题】:How to create GROUP BY on min and max date 【发布时间】:2019-07-12 16:57:27 【问题描述】:

我有一个这样的数据库表

emp_id start-date  end_date    title    location
111    1-JAN-2000  31-DEC-2003 MANAGER  NYO
111    1-JAN-2003  31-DEC-2005 MANAGER  BOM
111    1-JAN-2006  31-DEC-2007 CFO      NYO
111    1-JAN-2008  31-DEC-2015 MANAGER  NYO

我已经用 GROUP BY 和 min , max 函数创建了一个 SQL 代码

select emp_id,min(start_date),max(end_date),title
from table1
group by emp_id,title

预期是这样的:

111 1-JAN-2000 31-DEC-2005 MANAGER
111 1-JAN-2006 31-DEC-2007 CFO
111 1-JAN-2008 31-DEC-2015 MANAGER

我得到的是:

111 1-JAN-2000 31-DEC-2015 MANAGER 
111 1-JAN-2006 31-DEC-2007 CFO

【问题讨论】:

每一行代表一个组。您的组定义为:emp_id 和 title。因此,您预期中的第 1 行和第 3 行被归为一组...为了帮助您,我们可能需要查看 table1 中的示例数据。 所以你不想要 min 和 max - 你想要在 title 值发生变化时启动一个新组的东西。 @kbball : 我添加了位置栏 @DanielM :你能建议我一个解决方法吗? 【参考方案1】:

这是日期链的一种差距和孤岛问题。我建议使用left join 来查找岛屿的起点。然后是累积和聚合:

select emp_id, title, min(start_date), max(end_date)
from (select t.*,
             sum(case when tprev.emp_id is null then 1 else 0 end) over
                 (partition by t.emp_id, t.title order by t.start_date) as grouping
      from t left join
           t tprev
           on t.emp_id = tprev.emp_id and
              t.title = tprev.title and
              t.start_date = tprev.end_date + 1
     ) t
group by grouping, emp_id, title;

【讨论】:

以上代码按照我的初始测试运行。将与我的代码集成,让我们都知道它是怎么回事。谢谢【参考方案2】:

尝试如下使用窗口函数找到间隙并使其成为组

with cte1 as
(
select a.*,
row_number()over(partition by emp_id,title order by start-date) rn,
row_number() over(order by start-date) rn1
from table_name a
) select emp_id,
  min(start-date),
  max(end_date),
  max(title)
  from cte1 group by emp_id, rn1-rn

demo link

【讨论】:

以上是关于如何在最小和最大日期创建 GROUP BY的主要内容,如果未能解决你的问题,请参考以下文章

如何在某个时间段内进行 GROUP BY?

如何在以下场景中使用 Oracle Group BY

在 GROUP BY 中选择具有最大日期的整行

如何在 GROUP BY 之前订购此数据库 [重复]

mysql在group by之后如何获取每一组中id最大的那一行

sql 语句,在group by 中选最大值max的问题