时间列转行再转置为新交叉表-AI实现方案

简介: 本题要求将交叉表(ID+PartNum为行头、三个时间字段为列头)动态转置:先列转行(UNION ALL展开时间点并映射为ENTERED/PICKED/DELIVERED),过滤空值,拼接列名(如“50A_100”),再行转列。SQLazy通过两步旋转+分步计算实现免写死列名、可调试、语义清晰的动态透视,大幅降低复杂转置逻辑的开发与维护成本。

问题描述

表 tb 可以看成一个交叉表:ID 与 PartNum 两个字段的组合是行头,EnteredOn、PickedTime、DeliveredTime 三个字段名是列头,格子里放的是时间点。行头的内容和数量都不固定。现在要把这张表翻过来:原来的格子(时间点)变成新表的行头,原来的行头(PartNum 与 ID 的组合)变成新表的列头,原来的三个列头换成字符串 ENTERED、PICKED、DELIVERED 填进格子里。

源数据
image.png
期望结果
列头是 PartNum 与 ID 拼成的组合,行头是时间点,格子里是动作名:
image.png
第一行 2024-03-28 08:59:13.727 落在 50A_100 这一列,值是 ENTERED,说明这是 ID=100、PartNum=50A 这条记录的进入时间。同一列往下还能看到 PICKED 和 DELIVERED 两行,分别是这条记录的取件时间和送达时间。也就是说,原来横着排在一行里的三个时间点,现在竖着排成了一列。

ID=171 和 ID=211 这两条记录只有进入时间,取件和送达是空的,所以结果里 50A_171 和 70B_211 这两列各只有一个 ENTERED,没有 PICKED 和 DELIVERED。空值必须先滤掉,否则会在新表里多出两行没有意义的时间点。

新表的列数等于源数据里 "行头组合" 的个数(本例 4 个),行数等于三个时间列里非空值的总条数(本例 6 加 2 共 8 条),两个方向都不固定,所以这道题不能用写死列名的办法做。

SQLazy 分步实现

这道题的本质是旋转两次。第一次把三个时间列旋转成行,让每个时间点单独占一行,同时记下这个时间点属于哪个动作;第二次把行再旋转成列,用 PartNum 与 ID 拼出来的组合当新列名。两次旋转都用旋转功能,第一次用它的逆向模式(列转行),第二次用默认模式(行转列)。中间还要做两件小事:滤掉空的时间点,把动作的字段名换成题目要求的短名。
下面逐一解释这些步骤。
image.png
第 1 步:把三个时间列转成行

pivot group ID, PartNum; name action_type; value t_stamp; inverse

这是本题的第一个关键动作。旋转功能默认是把行转成列,加上逆向参数就切换成列转行:ID 和 PartNum 两个分组列保持不动,其余三个时间列被展开成行,原来的列名 EnteredOn、PickedTime、DeliveredTime 变成新列 action_type 的值,原来的列值(时间点)变成新列 t_stamp 的值。

这一步之后,一行宽记录变成了三行长记录:ID=100 这条记录会变成三行,分别带着 EnteredOn、PickedTime、DeliveredTime 三个动作名和对应的时间点。行头组合有几个、列头有几个都不影响这个动作,所以行头数量不固定也不怕。

a44b8b35ebd631ef94bd531c507ebaf5_29c16f5bd3ff42c0835cb1e6d7d0dd3b_Picture12.png
第 2 步:滤掉空的时间点
filter (t_stamp notnull)
源数据里 ID=171 和 ID=211 这两条记录只有进入时间,取件和送达是空的。列转行会把空值也展开成行,这些行没有实际意义,先滤掉。判断空值用的是非空函数,整个条件式写在筛选功能的括号里。
2272e4f7ee9cbfbe97ec4a56e1b5a775_d6cdc207d64e4cbc80788c2fe8cc09c6_Picture13.png
第 3 步:把动作名换成题目要求的短名
compute if(action_type = “EnteredOn” then “ENTERED”, action_type = “PickedTime” then “PICKED”, action_type = “DeliveredTime” then “DELIVERED”) as status
题目要求格子里的内容是 ENTERED、PICKED、DELIVERED,而列转行得到的是原始的列名,所以用计算列加条件函数做一次映射:动作名等于 EnteredOn 就换成 ENTERED,等于 PickedTime 就换成 PICKED,等于 DeliveredTime 就换成 DELIVERED,结果写入新列 status。条件函数可以依次判断多个条件并返回对应的值,正好适合这种多个等值分支的映射。
cb6114c3cb5e48022a6c78bf26bfe44f_5aa7ca07f54c407bb32c0c82b509fa3f_Picture14.png
第 4 步:拼出新表的列名
compute concat(PartNum, “_”, ID) as col_name
新表的列头是 PartNum 与 ID 用下划线拼起来的组合,比如 50A_100。用连接函数把两个字段和中间的下划线拼成一个字符串,写入新列 col_name。列名不是事先知道的,是数据算出来的,这也是这道题不能写死列名的原因。

2eecd65a4ff00c38b6003449e13a7e7c_74739ef293964406887fe778a004038b_Picture15.png
第 5 步:只留需要的三列
derive t_stamp, col_name, status
前面的步骤留下了 ID、PartNum、action_type 等中间列,第二次旋转只需要时间点、列名、动作名三列,用导出表挑出来即可。
220c5bfc692ac7bab70dddb1dfdd9990_cb3963f6a7534791a188d16b74f096e7_Picture16.png
第 6 步:把行转成列
pivot group t_stamp; name col_name; value status
第二次旋转不写计算方法,用默认模式行转列:按 t_stamp 分组,col_name 的每个取值变成一个新列的列名,status 的值填进对应的格子。同一行同一列在数据里只会出现一次(一个时间点只属于一条记录的一个动作),所以不需要指定聚合算法,缺省的取组内第一条就够了。
这里不写逆向参数,与第 1 步正好相反:第 1 步是把列转成行,这一步是把行转成列,两次旋转合起来完成了整张表的翻转。
575c59beb03ff91d567facb3410b7b07_987be3d28a094394902af5603e908057_Picture17.png
编译生成 SQL
确认上述 6 步逻辑后,SQLazy 编译器自动生成原生 SQL(这里是 MySQL 语法):

WITH t1 AS (
    SELECT ID, PartNum, 'EnteredOn' AS action_type, EnteredOn AS t_stamp
    FROM tb
    UNION ALL
    SELECT ID, PartNum, 'PickedTime' AS action_type, PickedTime AS t_stamp
    FROM tb
    UNION ALL
    SELECT ID, PartNum, 'DeliveredTime' AS action_type, DeliveredTime AS t_stamp
    FROM tb
  ),
  t2 AS (
    SELECT ID, PartNum, EnteredOn, PickedTime, DeliveredTime
    FROM t1
    WHERE t_stamp IS NOT NULL
  ),
  t4 AS (
    SELECT ID, PartNum, action_type, t_stamp
      , CASE
        WHEN action_type = 'EnteredOn' THEN 'ENTERED'
        WHEN action_type = 'PickedTime' THEN 'PICKED'
        WHEN action_type = 'DeliveredTime' THEN 'DELIVERED'
        ELSE NULL
      END AS status
      , concat_ws('', PartNum, '_', ID) AS col_name
    FROM t2
  ),
  t5 AS (
    SELECT t_stamp, col_name, status
      , FIRST_VALUE(status) OVER (PARTITION BY t_stamp, col_name ORDER BY NULL) AS FIRST_2
    FROM t4
  )
SELECT t_stamp
  , MIN(CASE
    WHEN col_name = '50A_100' THEN FIRST_2
  END) AS `50A_100`
  , MIN(CASE
    WHEN col_name = '50A_171' THEN FIRST_2
  END) AS `50A_171`
  , MIN(CASE
    WHEN col_name = '60B_125' THEN FIRST_2
  END) AS `60B_125`
  , MIN(CASE
    WHEN col_name = '70B_211' THEN FIRST_2
  END) AS `70B_211`
FROM t5
GROUP BY t_stamp

SQLazy 让你用业务语言描述逻辑,而不是用 SQL 语法写嵌套查询。这道题的两次翻转各用一句旋转语句就能表达:第一次用逆向模式把三个时间列展开成行,第二次用默认模式把行再转成列,读代码时一眼就能看出 "先列转行、再行转列" 这两步,不必在 SQL 里逐个手写 UNION ALL 和写死的 CASE 分支。

旋转功能的两种模式是这道题的关键。同一个功能,加不加逆向参数就切换了方向,而两个方向共用分组列、标题列、取值列这套说法,业务上说的 "哪个字段当新列名、哪个字段当新值" 可以直接照抄成参数,不需要先想清楚 SQL 里该用 CASE 还是该用 UNION。

新列名来自数据本身(PartNum 与 ID 拼接)时,SQL 只能把列名写死在语句里,数据一变就得改语句;SQLazy 把拼接列名也当成一步普通的计算列,列名随数据自动生成,行头和列头数量变化都不用改代码。

分步计算让每一步都能单独查看:第 1 步之后能看到展开后的长表,第 2 步之后能看到空值已经被滤掉,第 4 步之后能看到拼好的列名,出错时不必把整条语句跑完再猜哪一段不对。

相关文章
|
云安全 安全 网络安全
|
6天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
1969 1
|
12天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
2039 40
|
9天前
|
Web App开发 人工智能 前端开发
2026 年 AI 浏览器怎么选?Ego Lite、Tabbit、Chrome DevTools MCP 深度对比,开发者到底该用哪个?
2026年AI浏览器选型指南:Ego Lite专注多Agent协同(Mac优先),Tabbit国产首选,原生支持Windows与Codex控制;Chrome DevTools MCP非浏览器而是开发者利器,深度集成Console/Network/Performance调试能力,让AI真正“看懂并验证”前端代码。
1332 3
|
13天前
|
JSON 程序员 数据格式
最新版Notepad++下载、安装、配置保姆级教程(附官网安装包)
Notepad++ 是一款免费开源、轻量快速的 Windows 文本编辑器,支持多标签、语法高亮、代码折叠与宏录制,体积小、启动快、资源占用低,兼容 x64/x32/ARM 架构,是程序员和文字工作者的高效利器。
2495 0
|
6天前
|
安全 应用服务中间件 Go
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
PHP2Shell 双 RCE 已遭在野利用:WordPress、Drupal 全在射程内,nginx 其实另有洞。拆成因与修复顺序
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
|
13天前
|
安全 Linux 芯片
【万字长文】Ollama下载、安装、配置、使用保姆级教程(2026最新图解)
Ollama 是一款免费开源的本地大模型运行工具,支持 DeepSeek、Qwen 等主流模型,一条命令即可下载运行。2026 最新版 v0.35.1 官方安装包(1.47GB)已提供国内直连下载,纯本地、离线可用、无广告、无隐私泄露风险。
1251 5
|
6天前
|
开发者 索引
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
Open Plugin Market 是一个开放插件索引平台,收录800+优质DSH插件,支持分类浏览、智能推荐与随机发现。无需安装市场,粘贴索引地址即可一键接入,网页版直访 dshopen.org,助力小开发者被看见。(239字)
1370 1
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
|
5天前
|
安全 程序员 应用服务中间件
PHP 被曝两大致命漏洞,请所有程序员抓紧做这件事!
PHP 官方发布了紧急安全更新,一口气修复了两个严重漏洞。如果网站和服务器用了 PHP 应该怎么处理?漏洞的原理是什么?本文给你讲清楚
618 0

热门文章

最新文章