首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对mysql表中的行进行分组,直到值发生变化?(不使用变量)

如何对mysql表中的行进行分组,直到值发生变化?(不使用变量)
EN

Stack Overflow用户
提问于 2022-10-19 04:09:47
回答 1查看 45关注 0票数 0

我有一个名为“employees”的表,我只想按行的指定进行分组,直到它改变为止。

请查看示例表

代码语言:javascript
复制
Id  Name    Designation     Employee Id Last Modified   
1   John    General Manager     1       15-10-2001  
2   John    General Manager     1       05-11-2001  
3   John    Product Manager     1       06-11-2001  
4   John    Product Manager     1       15-11-2001  
5   John    General Manager     1       30-12-2001  

预期输出

代码语言:javascript
复制
Employee Id Name    Designation     Valid From  Valid to
1           John    General Manager 15-10-2001  05-11-2001
1           John    Product Manager 06-11-2001  15-12-2001
1           John    General Manger  16-12-2001  30-12-2001

我试着使用group by子句,但它只给了我2行(总经理、产品经理)。但是我想要一个输出,如表所示,我可以解决一个更大的问题,包括每个角色的开始日期和结束日期。提前谢谢!.

EN

回答 1

Stack Overflow用户

发布于 2022-10-20 01:09:58

给你:

代码语言:javascript
复制
WITH cte1 AS(
  SELECT EmployeeId, 
        LastModified,
        Designation,
        LEAD(Designation) OVER (ORDER BY EmployeeId, LastModified) AS NextDesg,
        LAG(LastModified) OVER (ORDER BY EmployeeId, LastModified) AS PrevLm
   FROM mytable),
  cte2 AS (
SELECT *,
       ROW_NUMBER()
           OVER (PARTITION BY EmployeeId ORDER BY LastModified) AS NewGroup
  FROM cte1
WHERE (Designation != NextDesg OR NextDesg IS NULL)
  ORDER BY LastModified) 
  
SELECT t.EmployeeId, t.Name, t.Designation, 
       MIN(t.LastModified) AS "Valid From", 
       MAX(t.LastModified) AS "Valid To",
       COALESCE(c1.NewGroup, c2.NewGroup) AS NwGr
  FROM mytable t
  LEFT JOIN cte2 c1 
ON t.EmployeeId=c1.EmployeeId
 AND t.LastModified=c1.LastModified
 LEFT JOIN cte2 c2
ON t.EmployeeId=c2.EmployeeId
 AND t.LastModified=c2.PrevLm
  GROUP BY t.EmployeeId, t.Name, t.Designation, NwGr;

这里的主要思想是将每个集合指定为一个新的组,然后根据结果对其进行分组。

我们从两次执行公共表表达式开始。第一项是:

代码语言:javascript
复制
WITH cte1 AS(
  SELECT EmployeeId, 
        LastModified,
        Designation,
        LEAD(Designation) OVER (ORDER BY EmployeeId, LastModified) AS NextDesg,
        LAG(LastModified) OVER (ORDER BY EmployeeId, LastModified) AS PrevLm
   FROM mytable)

我使用LEAD()获取要用作分隔符的下一个Designation值,使用LAG()获取最后查询中的第二个LEFT JOINON中使用的前一个LastModified值。

第二cte

代码语言:javascript
复制
cte2 AS (
SELECT *,
       ROW_NUMBER()
           OVER (PARTITION BY EmployeeId ORDER BY LastModified) AS NewGroup
  FROM cte1
WHERE (Designation != NextDesg OR NextDesg IS NULL)
  ORDER BY LastModified)

这里我使用了使用LEAD() (第一个cte )返回的值来标识Designation中的更改,然后添加ROW_NUMBER()函数作为NewGroup生成。

然后在最后一个查询中:

代码语言:javascript
复制
...
FROM mytable t
  LEFT JOIN cte2 c1 
ON t.EmployeeId=c1.EmployeeId
 AND t.LastModified=c1.LastModified
 LEFT JOIN cte2 c2
ON t.EmployeeId=c2.EmployeeId
 AND t.LastModified=c2.PrevLm
...

我用cte2从主表中做了两次cte2,第一次是通过EmployeeIdLastModified进行匹配,第二次是通过EmployeeID和从LAG()函数获得的以前的LastModified值进行匹配。

演示小提琴

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74119765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档