【问题标题】:SQL Query to merge records用于合并记录的 SQL 查询
【发布时间】:2019-01-20 02:39:25
【问题描述】:

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

我想合并第一条、第二条和第三条记录(ORDERED BY START_DATE),因为它们只是扩展并产生以下输出

如您所见,我已合并前 3 条记录,并从第一行获取 START_DATE,并从第三行结束 END_DATE

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

【问题讨论】:

  • 为什么三个不同的数据库系统都有不同的SQL方言?或者该解决方案是否需要在 MySQL、SQL Server 和 Oracle 数据库中运行?
  • SQL 也被定义为 orderless。诸如“前 3 条记录”、“第一条记录”、“第二条记录”、“第三条记录”之类的含义定义也是 无意义。您是否有一个列可以用来识别顺序?就像自动递增的 id 或 datetime 列在插入/更新时更新
  • 另外我建议您将 start_date 和 end_date 数据转换为 DATETIME 数据库。
  • 我标记 MySQL、SQL Server 和 Oracle 的原因是因为我们需要为所有 3 个数据库提供解决方案。同意。我会标记其中之一。关于无序,我试图建立的顺序是通过 START_DATE。

标签: sql sql-server merge


【解决方案1】:

这是一个孤岛问题,但有日期范围。最通用的解决方案是假设行之间可能存在间隙(尽管您的数据没有这种情况)。

您可以通过找出“恒定期”的开始位置来解决这个问题。在这种情况下,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】:

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

适用于 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

【讨论】:

  • 可能不会像预期的那样工作日期格式看起来像是一个无效的 MySQL 日期格式字符串。这将适用于 DATETIME 数据类型或遵循有效 MySQL 数据格式的 CHAR|VARCHAR 数据类型,如yyyy-mm-dd
  • 这个答案不会起作用,因为它也会结合最后一条记录。我不想合并最后一条记录。只有共享相同“员工类型”的连续记录才应合并
  • @RaymondNijland 我和你在一起,但由于它是来自 Excel 的图片,我假设实际数据是日期时间,如果不是,那么 OP 需要对其进行转换。
  • @Senthil 我已经更新了我的答案,试图涵盖所有三个 dbms,因为你想要对所有三个都有效的东西。
  • @iSR5,感谢您的回答,但如果所有结束日期都在同一年,则查询无效。
【解决方案3】:

以下查询有助于解决问题

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 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    • 2021-02-09
    • 2011-11-01
    • 2011-07-18
    • 1970-01-01
    相关资源
    最近更新 更多