从垂直行中选择记录并转换水平行

Posted

技术标签:

【中文标题】从垂直行中选择记录并转换水平行【英文标题】:Select records from vertical row and transform horizontal row 【发布时间】:2021-09-24 18:59:06 【问题描述】:

我正在处理 SQL Server 查询,以获取将处理多个任务代码的用户列表的最后一个 Badge_In_Out_Time。

task_mgmt - 表名

表格列如下

Task_Sn UserName Task_Code Action Badge_IN_OUT_TIME
1 Andy BLOG START 2021-07-15 08:11:45.000
2 Andy BLOG END 2021-07-15 10:11:45.000
3 Becky ACCTS START 2021-07-15 11:11:45.000
4 Chris TAX START 2021-07-15 12:11:45.000
5 Andy SOCMEDIA START 2021-07-15 12:15:45.000
6 Becky ACCTS END 2021-07-15 12:25:45.000

我正在排除结果

UserName Task_Code Badge_IN_TIME Badge_OUT_TIME
Andy BLOG 2021-07-15 08:11:45.000 2021-07-15 10:11:45.000
Becky ACCTS 2021-07-15 11:11:45.000 2021-07-15 12:25:45.000
Chris TAX 2021-07-15 12:11:45.000
Andy SOCMEDIA 2021-07-15 12:15:45.000

我真的想不出任何关于这个的问题。我是 SQL 的初学者,我知道 CRUD 操作。这对我来说似乎超级复杂。

Select UserName,
       Task_Code,
       Badge_In_Time,
       Badge_Out_Time
from task_mgmt
order by Badge_IN_OUT_TIME desc

【问题讨论】:

根据问题指南,请展示您的尝试并告诉我们您发现了什么(在本网站或其他地方)以及为什么它不能满足您的需求。 我真的想不出任何关于这个的查询。我是 SQL 的初学者,我知道 CRUD 操作。这对我来说似乎超级复杂。 【参考方案1】:

只需通过将行聚合到所需级别(UserNameTaskCode)然后使用MAXMIN(CASE WHEN .... END) 进行旋转来进行简单的旋转

像这样:

SELECT 
    tm.UserName
    ,tm.Task_Code
    ,MIN(CASE WHEN tm.Action = 'START' THEN tm.Badge_IN_OUT_TIME ELSE NULL END) AS Badge_IN_TIME
    ,MAX(CASE WHEN tm.Action = 'END' THEN tm.Badge_IN_OUT_TIME ELSE NULL END) AS Badge_OUT_TIME 
FROM 
    task_mgmt AS tm 
GROUP BY 
    tm.UserName
    ,tm.Task_Code

【讨论】:

谢谢。我会尝试这个解决方案并让你知道。真的很欣赏。【参考方案2】:

这是一种间隙和岛屿问题,这些岛屿是STARTEND的对。

有多种解决方案。在这里,我假设START 总是定义每个组的开头,可能有也可能没有END

我们可以使用带窗口的COUNT,按UserNameTask_Code 划分来计算每个岛的分组数。然后,我们也只需按新的分组编号进行分组,并旋转时间戳

SELECT
  t.UserName,
  t.Task_Code
  MIN(CASE WHEN t.Action = 'START' THEN t.Badge_IN_OUT_TIME END) Badge_IN_TIME,
  MAX(CASE WHEN t.Action = 'END'   THEN t.Badge_IN_OUT_TIME END) Badge_OUT_TIME
FROM (
    SELECT *,
        COUNT(CASE WHEN t.Action = 'START' THEN 1 END) OVER
           (PARTITION BY t.UserName, t.Task_Code
            ORDER BY t.Badge_IN_OUT_TIME ROWS UNBOUNDED PRECEDING) grp
    FROM task_mgmt t
) t
GROUP BY
  t.UserName,
  t.Task_Code
  t.grp;

【讨论】:

以上是关于从垂直行中选择记录并转换水平行的主要内容,如果未能解决你的问题,请参考以下文章

如何将水平行转换为垂直行

将自定义 CSS 导航栏从水平转换为垂直

带有 IntputLabel 和 Input 的 Material UI 网格放置在水平行中:如何要求垂直对齐位于标签的中间?

SQL:如何从重复行中选择第一条记录?

从 MySQL 查询中从百万行中选择第 N 条记录

SQL查询;水平到垂直