You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写MySQL查询实现行转列(员工考勤场景)

问题描述

我正在开发一款员工追踪应用,现有如下结构的MySQL数据表:

IDPersonIDTypeIDDateTime
1001IN2022-09-01T13:21:12
2001OUT2022-09-01T13:25:12
3001IN2022-09-01T14:21:12
4001OUT2022-09-01T14:25:12
5002IN2022-09-03T13:21:12
6002OUT2022-09-03T13:25:12
7002IN2022-09-03T14:21:12
8002IN2022-09-03T14:25:12
9002OUT2022-09-03T14:25:12
10002OUT2022-09-03T16:25:12
11002OUT2022-09-03T17:25:12
12002IN2022-09-04T16:25:12
13002IN2022-09-05T17:25:12

我希望创建一个视图,返回的记录先按PersonID排序,再按ID排序,同时将行转换为列,格式如下:

PersonIDInIDIn_DateTimeOutIDOut_DateTime
00112022-09-01T13:21:1222022-09-01T13:25:12
00132022-09-01T14:21:1242022-09-01T14:25:12
00252022-09-03T13:21:1262022-09-03T13:25:12
00272022-09-03T14:21:12nullnull
00282022-09-03T14:25:1292022-09-03T14:25:12
002nullnull102022-09-03T16:25:12
002nullnull112022-09-03T17:25:12
002122022-09-04T16:25:12nullnull
002132022-09-05T17:25:12nullnull

请问如何在MySQL中实现这个需求?


解决方案

要实现这个需求,核心是为每个PersonID下的IN和OUT记录分别分配分组内序号,再通过序号将对应的记录配对,同时保留无法匹配的单独记录。以下是具体实现步骤:

1. 创建视图的完整SQL语句

CREATE VIEW employee_tracking_view AS
WITH in_records AS (
    -- 提取所有IN记录,为每个员工的IN操作按ID顺序分配序号
    SELECT 
        PersonID,
        ID AS InID,
        DateTime AS In_DateTime,
        ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY ID) AS in_seq
    FROM your_table_name
    WHERE TypeID = 'IN'
),
out_records AS (
    -- 提取所有OUT记录,为每个员工的OUT操作按ID顺序分配序号
    SELECT 
        PersonID,
        ID AS OutID,
        DateTime AS Out_DateTime,
        ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY ID) AS out_seq
    FROM your_table_name
    WHERE TypeID = 'OUT'
)
-- 全连接匹配IN/OUT记录,保留所有单独的IN或OUT行
SELECT 
    COALESCE(i.PersonID, o.PersonID) AS PersonID,
    i.InID,
    i.In_DateTime,
    o.OutID,
    o.Out_DateTime
FROM in_records i
FULL JOIN out_records o 
    ON i.PersonID = o.PersonID 
    AND i.in_seq = o.out_seq
-- 按PersonID和序号排序,保证顺序符合要求
ORDER BY PersonID, COALESCE(i.in_seq, o.out_seq);

2. 逻辑说明

  • 分组序号分配:使用ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY ID),为每个员工的IN、OUT操作分别按原始ID顺序生成递增序号,确保后续能按顺序配对。
  • 全连接匹配:FULL JOIN会保留所有IN和OUT记录,即使没有对应的配对项(比如单独的IN或OUT),未匹配的字段会显示为NULL。
  • 排序规则:最终结果按PersonID分组,再按分组内序号排序,和需求中的顺序一致。

3. 注意事项

  • 该方案要求MySQL版本为8.0及以上,因为使用了窗口函数ROW_NUMBER()和CTE(WITH子句)。
  • 请将SQL中的your_table_name替换为你实际的数据表名称。

内容的提问来源于stack exchange,提问作者davor.geci

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:03:19