将一个组的连续日期合并在一起

发布于 2025-01-27 10:23:22 字数 2323 浏览 5 评论 0原文

我有一个看起来像这样的员工的桌子:

名称部门经理日期
员工1部门1经理x202101
员工1dept 1Manager x202102
雇员1雇员1dept 2Manager x202103
雇员1雇员1部长2经理X202104
雇员1部门1Manager 1Manager x202105
员工1部门1经理X202106
员工2部门1经理x202101
员工2雇员2 dept 1Manager x202102

我需要构建以下格式显示数据的视图:

名称部门经理有效_for_fromvalos valy_to
雇员1dept 1Manager x202101202102
雇员1部门2Manager x202103202104
员工1部门1Manager x202105999912
员工2dept 1Manager x202101999912

到目前为止,这就是为什么代码的样子:

WITH cte AS
(
   SELECT [Name], Department, Manager, Valid_From = min([Date]), Valid_To = max([Date]),
      RowNum = ROW_NUMBER() OVER (PARTITION BY [Name], ORDER BY max([Date]) DESC)
   FROM TestingTable
   WHERE ([Date] IS NOT NULL)
   GROUP BY [Name], Department, Manager
)
SELECT [Name], Department, Manager, Valid_From,
    CASE WHEN RowNum = 1 THEN 999912 ELSE Valid_To END AS Valid_To, CASE WHEN RowNum = 1 THEN 1 ELSE 0 END AS Is_Latest
FROM cte

输出就是这样 - IT组在雇员1在部门的间隔工作,该雇员1在部门工作了1,虽然我需要以2个不同的时间间隔。

名称部门经理有效_for_to
雇员1部门1经理X202101999912
员工1部门2Manager x202103202104
员工2dept 1Manager x202101999912

我尝试了一些lag和Lag功能以比较日期,但我迷失了。

I have a table with employees that looks like this:

NameDepartmentManagerDate
Employee 1Dept 1Manager X202101
Employee 1Dept 1Manager X202102
Employee 1Dept 2Manager X202103
Employee 1Dept 2Manager X202104
Employee 1Dept 1Manager X202105
Employee 1Dept 1Manager X202106
Employee 2Dept 1Manager X202101
Employee 2Dept 1Manager X202102

I need to build a view that shows the data in the following format:

NameDepartmentManagerValid_FromValid_To
Employee 1Dept 1Manager X202101202102
Employee 1Dept 2Manager X202103202104
Employee 1Dept 1Manager X202105999912
Employee 2Dept 1Manager X202101999912

So far, this is what why code looks like:

WITH cte AS
(
   SELECT [Name], Department, Manager, Valid_From = min([Date]), Valid_To = max([Date]),
      RowNum = ROW_NUMBER() OVER (PARTITION BY [Name], ORDER BY max([Date]) DESC)
   FROM TestingTable
   WHERE ([Date] IS NOT NULL)
   GROUP BY [Name], Department, Manager
)
SELECT [Name], Department, Manager, Valid_From,
    CASE WHEN RowNum = 1 THEN 999912 ELSE Valid_To END AS Valid_To, CASE WHEN RowNum = 1 THEN 1 ELSE 0 END AS Is_Latest
FROM cte

The output is this - it groups the intervals that employee 1 has worked in department 1, while I need it in 2 different chronological intervals.

NameDepartmentManagerValid_FromValid_To
Employee 1Dept 1Manager X202101999912
Employee 1Dept 2Manager X202103202104
Employee 2Dept 1Manager X202101999912

I experimented a bit with the lag and lead functions to compare the dates, but I'm lost.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鯉魚旗 2025-02-03 10:23:22

看来您需要连续将每个员工 - 居民经理人分组在一起。可以这样做:

with cte1 as (
    select name
         , department
         , manager
         , datefromparts(date / 100, date % 100, 1) as yymm
    from t
), cte2 as (
    select *
         , case when lag(yymm) over (partition by name, department, manager order by yymm) = dateadd(month, -1, yymm) then 0 else 1 end as new_grp
    from cte1
), cte3 as (
    select *
         , sum(new_grp) over (partition by name, department, manager order by yymm) as grp_num
    from cte2
)
select name
     , department
     , manager
     , min(yymm) as valid_from
     , max(yymm) as valid_to
from cte3
group by name, department, manager, grp_num
order by name, valid_from, department, manager

请注意,我必须将年度月份转换为日期,以便更容易地进行比较。结果:

姓名部门经理有效_fromvaly_to
雇员1部长1经理x2021-01-012021-02-01
雇员1部长1部长x2021-03-03-012021-04-04-01
雇员1 dept 1Manager 1 Manager x2021-05-01-05-012021-06-01
员工2部门1Manager x2021-01-012021-02-02-02-01

9999-12-01是trivial例如,您可以检查Lead(有效_from)是否(按vall valom按名称顺序划分)为null。

Looks like you need to group consecutive year-months per employee-department-manager together. It could be done like so:

with cte1 as (
    select name
         , department
         , manager
         , datefromparts(date / 100, date % 100, 1) as yymm
    from t
), cte2 as (
    select *
         , case when lag(yymm) over (partition by name, department, manager order by yymm) = dateadd(month, -1, yymm) then 0 else 1 end as new_grp
    from cte1
), cte3 as (
    select *
         , sum(new_grp) over (partition by name, department, manager order by yymm) as grp_num
    from cte2
)
select name
     , department
     , manager
     , min(yymm) as valid_from
     , max(yymm) as valid_to
from cte3
group by name, department, manager, grp_num
order by name, valid_from, department, manager

Note that I had to convert the year-months to dates for easier comparison. Result:

namedepartmentmanagervalid_fromvalid_to
Employee 1Dept 1Manager X2021-01-012021-02-01
Employee 1Dept 2Manager X2021-03-012021-04-01
Employee 1Dept 1Manager X2021-05-012021-06-01
Employee 2Dept 1Manager X2021-01-012021-02-01

Replacing the last valid_to for each employee with 9999-12-01 is trivial e.g. you can check if lead(valid_from) over (partition by name order by valid_from) is null.

十二 2025-02-03 10:23:22

Looks like a kind of gaps and islands problem with a twist regarding the open intervals detection

select distinct Name, Department, Manager, 
      min([date]) over(partition by Name, g) fromd,
      max([date]) over(partition by Name, g) tod
from (
  select *, sum(flag) over(partition by Name order by [date]) g
  from (
    select Name, Department, Manager,
      case when lead(name) over(partition by Name order by [date]) is null then 999912 else [date] end [date],
      case when department != lag(Department, 1, '') over(partition by Name order by [date]) 
            or  Manager != lag(Manager, 1, '') over(partition by Name order by [date])
           then 1 else 0 end flag
    from tbl
  ) t
) t
order by fromd

db<>小提琴

Looks like a kind of gaps and islands problem with a twist regarding the open intervals detection

select distinct Name, Department, Manager, 
      min([date]) over(partition by Name, g) fromd,
      max([date]) over(partition by Name, g) tod
from (
  select *, sum(flag) over(partition by Name order by [date]) g
  from (
    select Name, Department, Manager,
      case when lead(name) over(partition by Name order by [date]) is null then 999912 else [date] end [date],
      case when department != lag(Department, 1, '') over(partition by Name order by [date]) 
            or  Manager != lag(Manager, 1, '') over(partition by Name order by [date])
           then 1 else 0 end flag
    from tbl
  ) t
) t
order by fromd

db<>fiddle

想你只要分分秒秒 2025-02-03 10:23:22

尝试以下操作:

with tbl1 as (select 
    [name]
    ,[department]
    ,[manager]
    ,[date]
    ,ROW_NUMBER () over (partition by name, department, manager order by name, department) as rownum 
from employees)
select  [name]
    ,[department]
    ,[manager]
    ,[date] as [valid_from]
    ,(select [date] from tbl1 t2 
    where t2.[rownum]  = t1.[rownum] + 1
    and t1.name = t2.name
    and t1.department = t2.department
    and t1.manager = t2.manager
    ) as [valid_to]
from tbl1 t1
where rownum % 2 = 1
order by name, valid_from

它缺少999912,因为我不了解在底部两行中更换的逻辑。

try this:

with tbl1 as (select 
    [name]
    ,[department]
    ,[manager]
    ,[date]
    ,ROW_NUMBER () over (partition by name, department, manager order by name, department) as rownum 
from employees)
select  [name]
    ,[department]
    ,[manager]
    ,[date] as [valid_from]
    ,(select [date] from tbl1 t2 
    where t2.[rownum]  = t1.[rownum] + 1
    and t1.name = t2.name
    and t1.department = t2.department
    and t1.manager = t2.manager
    ) as [valid_to]
from tbl1 t1
where rownum % 2 = 1
order by name, valid_from

its missing the 999912 as I dont understand the logic for replacement in the bottom two rows.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文