没有键名时如何对数据进行从窄到宽的转换
Posted
技术标签:
【中文标题】没有键名时如何对数据进行从窄到宽的转换【英文标题】:How to do a narrow to wide transformation of data when there are no key names 【发布时间】:2019-11-03 01:51:47 【问题描述】:我有一个如下所示的数据集:
school_id | class_id | recess_num | student_id
----------------------------------------------
27 | 6 | 2 | 12
27 | 6 | 2 | 53
27 | 6 | 2 | 23
27 | 6 | 2 | 47
27 | 14 | 2 | 6
27 | 14 | 2 | 51
27 | 14 | 2 | 42
27 | 14 | 2 | 60
这个想法是来自不同班级的某些学生同时出去休息。几个要点:
每个班级有相同数量的学生同时外出 每个班级每次外出的学生人数始终相同(假设一次有 4 个)我想为这些数据创建一个宽表表示形式,其中每个课间休息的所有学生都被记录在一行中。由于学生的数量始终相同,我想为每个学生创建新列:
school_id | class_id | recess_num | student_1 | student_2 | student_3 | student_4
---------------------------------------------------------------------------------
27 | 6 | 2 | 12 | 53 | 23 | 47
27 | 14 | 2 | 6 | 51 | 42 | 60
仅使用 SQL 查询来完成此任务的最佳方法是什么?
【问题讨论】:
。 .用您正在使用的数据库标记您的问题。 【参考方案1】:你可以做条件聚合:
select
school_id,
class_id,
recess_num,
max(case when rn = 1 then student_id end) student_1,
max(case when rn = 2 then student_id end) student_2,
max(case when rn = 3 then student_id end) student_3,
max(case when rn = 4 then student_id end) student_4
from (
select
t.*,
row_number()
over(partition by school_id, class_id, recess_num order by student_id) rn
from mytable t
) t
group by
school_id,
class_id,
recess_num
内部查询对学校/班级/课间休息组中的学生进行排名,按 id 递增排序。然后外部查询使用条件聚合对数据进行透视。
请注意,这不会产生与您的预期结果完全相同的学生列顺序。但是,这似乎是一种按 id 对学生进行排序的更一致的方法(在这方面,您的预期结果似乎不一致)。
Demo on DB Fiddle:
学校ID | class_id |凹槽编号 |学生_1 |学生_2 |学生_3 |学生_4 --------: | --------: | ---------: | --------: | --------: | --------: | --------: 27 | 6 | 2 | 12 | 23 | 47 | 53 27 | 14 | 2 | 6 | 42 | 51 | 60【讨论】:
如果有多个相同的学生ID,可以使用排名【参考方案2】:select
school_id,
class_id,
recess_num,
case when student_id=12 then student_id end as student1,
case when student_id=53 then student_id end as student2,
case when student_id=23 then student_id end as student3,
case when student_id=47 then student_id end as student4,
from table
group by
school_id,
class_id,
recess_num
【讨论】:
我需要比这更通用的东西,我想为所有class_id
s 做,我给出的例子只是数据的一小部分
这对于所有班级 id 都是通用的,就好像 ypu cpuld 在 group by 除了学生 id 之外,其他列被列为通用。如果您的数据库支持枢轴,则可以将其用作枢轴用于将行转换为列。如果没有,那么您可以使用上面发布的 2 个回答中的任何一个。在上面的答案中,如果您确定使用提到的这些值,学生 ID 最多为 4 或更少,那么可以使用上面的其他方法,如果您有很多数据未知的值,则使用您选择的其他值以上是关于没有键名时如何对数据进行从窄到宽的转换的主要内容,如果未能解决你的问题,请参考以下文章