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

SQL行转列问题:将日期映射为对应天数并匹配状态

解决方案:行转列实现状态按星期展示

你当前的UNION ALL只是将两个日期的查询结果拼接,没有合并同一用户的记录,所以会出现多行。要实现期望的结果,需要用行转列的方式,以下是两种常用方法:

方法一:CASE表达式+聚合函数(通用多数数据库)

通过CASE判断日期,配合MAX/MIN聚合函数,将同一用户的多行记录合并为一行:

SELECT
    PersonID,
    Event,
    Name,
    -- 匹配周一的日期,取出对应状态
    MAX(CASE WHEN CAST(EventDate AS DATE) = '1900-12-31' THEN Status END) AS Monday,
    -- 匹配周二的日期,取出对应状态
    MAX(CASE WHEN CAST(EventDate AS DATE) = '1901-01-01' THEN Status END) AS Tuesday
FROM People
-- 可选:过滤目标日期范围,减少数据处理量
WHERE CAST(EventDate AS DATE) IN ('1900-12-31', '1901-01-01')
-- 按用户唯一标识分组,合并同一用户的记录
GROUP BY PersonID, Event, Name

原理说明:

  • CASE表达式仅在日期匹配时返回Status,否则返回NULL
  • MAX函数会自动忽略NULL值,保留对应日期的有效状态
  • GROUP BY将同一PersonID+Event+Name的记录合并为一行

方法二:PIVOT算子(适用于SQL Server等支持的数据库)

如果你的数据库支持PIVOT语法,可以更简洁地实现行转列:

SELECT
    PersonID,
    Event,
    Name,
    -- 将日期列重命名为对应的星期
    [1900-12-31] AS Monday,
    [1901-01-01] AS Tuesday
FROM (
    -- 子查询预处理,提取需要的字段并格式化日期
    SELECT
        PersonID,
        Event,
        Name,
        Status,
        CAST(EventDate AS DATE) AS EventDateStr
    FROM People
    WHERE CAST(EventDate AS DATE) IN ('1900-12-31', '1901-01-01')
) AS SourceTable
PIVOT (
    -- 聚合状态值
    MAX(Status)
    -- 指定要转成列的字段(日期)
    FOR EventDateStr IN ([1900-12-31], [1901-01-01])
) AS PivotTable

原理说明:

  • 子查询先将日期转为字符串格式,作为后续转列的标识
  • PIVOT将日期行转为列,并用MAX聚合取出对应状态
  • 最后将日期列名重命名为对应的星期名称

扩展到周一至周五

后续需要扩展到更多日期时,只需在CASE表达式或PIVOT的列列表中添加对应日期的判断即可,比如:

-- 扩展示例:添加周三、周四、周五
MAX(CASE WHEN CAST(EventDate AS DATE) = '1901-01-02' THEN Status END) AS Wednesday,
MAX(CASE WHEN CAST(EventDate AS DATE) = '1901-01-03' THEN Status END) AS Thursday,
MAX(CASE WHEN CAST(EventDate AS DATE) = '1901-01-04' THEN Status END) AS Friday

内容的提问来源于stack exchange,提问作者f00balls

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:39:18