代码之家  ›  专栏  ›  技术社区  ›  Senthil

用于合并记录的SQL查询

  •  0
  • Senthil  · 技术社区  · 7 年前

    我在SQL Server数据库中有一个Employee表,其中包含以下列和数据

    enter image description here

    我想合并第一、第二和第三个记录( 按开始日期订购 )因为它们只是扩展,产生以下输出

    enter image description here

    如您所见,我已经合并了前3个记录,并从第一行开始计算开始日期,从第三行结束计算结束日期。

    我需要一个SQL查询来创建这个输出,它将合并一个雇员ID的连续记录(基于时间),如果他们的雇员类型相同。

    3 回复  |  直到 7 年前
        1
  •  1
  •   Gordon Linoff    7 年前

    这是一个缺口和孤岛问题,但具有日期范围。最一般的解决方案是假设行之间可能存在间隙(尽管您的数据没有这样的间隙)。

    你可以解决这个问题,找出“恒常期”从哪里开始。在这种情况下, lag() 是你的朋友。然后,当您找到它们的起始位置时,一个累积和标识组,聚合解决了问题:

    select employee_id, employee_type,
           min(start_date), max(end_date)
    from (select e.*,
                 sum(case when start_date = dateadd(day, 1, prev_end_date) then 1 else 0 end) over
                     (partition by employee_id, employee_type) as grp
          from (select e.*,
                       lag(end_date) over (partition by employee_id, employee_type order by start_date) as prev_end_date
                from employee e
               ) e
         ) e
    group by employee_id, employee_type, grp;
    
        2
  •  1
  •   iSR5    7 年前

    这应该有帮助,尽管您应该真正标记目标数据库,并避免随机标记。

    用于SQL Server和MySQL

    SELECT 
        employee_id
    ,   employee_type 
    ,   MIN(start_date) start_date
    ,   MAX(end_date) end_date
    FROM 
        EMPLOYEE 
    GROUP BY 
        employee_id
    ,   employee_type 
    ,   YEAR(end_date)
    ORDER BY start_date
    

    甲骨文

    SELECT 
        employee_id
    ,   employee_type 
    ,   MIN(start_date) start_date
    ,   MAX(end_date) end_date
    FROM 
        EMPLOYEE 
    GROUP BY 
        employee_id
    ,   employee_type 
    ,   extract(year from end_date)
    ORDER BY start_date
    

    演示:

    SQL Server

    Oracle

    MySQL

        3
  •  0
  •   Senthil    7 年前

    下面的查询帮助解决了问题

    SELECT employee_id,
           employee_type,
           MIN(start_date) ,
           MAX(end_date) 
    FROM   (SELECT *,
    DENSE_RANK() OVER (PARTITION BY employee_id ORDER BY start_date),
    DENSE_RANK() OVER (PARTITION BY employee_id, employee_type ORDER BY start_date),
                    DENSE_RANK() OVER (PARTITION BY employee_id ORDER BY start_date) - 
                    DENSE_RANK() OVER (PARTITION BY employee_id, employee_type ORDER BY start_date) AS Grp
             FROM   employee) T
    GROUP  BY employee_id,
           employee_type,
              Grp
    ORDER  BY 3 asc