如何按星期名将行转列,实现指定数据表结构转换?
解决行转列的正确方法
你的思路方向有点搞反啦——你现在是把每个星期几作为一行,把行号转成列,但我们需要的是每个行号作为一行,把星期几转成列。
问题分析
你CTE里用RANK() OVER (PARTITION BY day_name ORDER BY day_date)生成每个星期几内部的行号rn是对的,但后续分组时你用了GROUP BY day_name,这就导致每个星期几只会出现在一行里,和我们要的结果正好相反。
正确的SQL代码
我们需要按rn分组,然后对每个星期几用CASE WHEN来提取对应的日期:
WITH dayz AS ( SELECT day_name, day_date, rn = ROW_NUMBER() OVER (PARTITION BY day_name ORDER BY day_date) -- 用ROW_NUMBER更合适,因为每个日期都是唯一的 FROM ISP_Cloud_DaysFromSession ) SELECT Monday = MAX(CASE WHEN day_name = 'Monday' THEN day_date END), Tuesday = MAX(CASE WHEN day_name = 'Tuesday' THEN day_date END) -- 如果还有其他星期几,可以继续加类似的CASE语句 FROM dayz GROUP BY rn ORDER BY rn;
代码解释
- CTE部分:用
ROW_NUMBER()(比RANK()更适合这里,因为每个日期都是唯一的,不会有并列排名)给每个星期几的日期按顺序分配行号rn,比如Monday的四个日期分别是rn=1到4,Tuesday的三个日期是rn=1到3。 - 主查询部分:按
rn分组,这样每个rn对应一行结果。然后用CASE WHEN筛选出对应星期几的日期,用MAX()(或者MIN(),因为每个rn+day_name组合只有一个值)来聚合,确保每个单元格只有一个日期值。 - 排序:最后按
rn排序,保证日期是按顺序排列的。
这样运行出来的结果就和你想要的完全一致啦:
| Monday | Tuesday |
|---|---|
| 2018-01-08 00:00:00.000 | 2018-01-16 00:00:00.000 |
| 2018-01-15 00:00:00.000 | 2018-01-23 00:00:00.000 |
| 2018-01-22 00:00:00.000 | 2018-01-30 00:00:00.000 |
| 2018-01-29 00:00:00.000 |
内容的提问来源于stack exchange,提问作者mecnism
相关产品推荐
相关产品推荐

