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,否则返回NULLMAX函数会自动忽略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
相关产品推荐
相关产品推荐

