我有一个带有列StudentMarks的表Name, Maths, Science, English
数据就像

Name,  Maths, Science, English  
Tilak, 90,    40,      60  
Raj,   30,    20,      10


我想像下面这样排列它:

Name,  Subject,  Marks
Tilak, Maths,    90
Tilak, Science,  40
Tilak, English,  60


不用枢纽,我能够正确获取名称,标记,但无法将源表中的列名称获取到所需结果集中的Subject列。

如何实现?

到目前为止,我已经达到以下查询(获取名称,商标)

select Name, Marks from studentmarks
Unpivot
(
  Marks for details in (Maths, Science, English)

) as UnPvt


评论

您可以张贴您到目前为止所做的事情吗?查询/输出。

#1 楼

您的查询非常接近。您应该能够使用以下内容,包括最终选择列表中的subject

select u.name, u.subject, u.marks
from student s
unpivot
(
  marks
  for subject in (Maths, Science, English)
) u;


请参阅带有演示的SQL Fiddle

评论


@bluefeet有没有一种方法可以使您不需要指定名称(数学,科学,英语)?我正在对许多表执行此操作,这些表都具有相同的结构,但具有不同的列名。

– LBogaardt
17年2月8日在9:23

@LBogaardt不,您需要显式定义要包括的列。

– jjjjjjjjjjj
17年2月9日在15:32

@LBogaardt在这里看看我的答案,您可以使用动态sql取消透视,而无需指定列名。

– Taryn♦
17年2月9日在15:36



#2 楼

您还可以通过以下代码使用一系列逻辑来尝试标准sql取消透视方法。.
以下代码包含3个步骤:


为每个副本创建多个副本使用交叉连接的行(在这种情况下,也会创建主题列)
创建列“标记”并使用案例表达式填写相关值(例如:如果主题是科学,则从科学列中选择值)

删除任何空值组合(如果存在,则如果基本表中严格没有空值,则可以完全避免使用表表达式)

 select *
 from 
 (
    select name, subject,
    case subject
    when 'Maths' then maths
    when 'Science' then science
    when 'English' then english
    end as Marks
from studentmarks
Cross Join (values('Maths'),('Science'),('English')) AS Subjct(Subject)
)as D
where marks is not null;




评论


这也适用于任何RDBMS!值(如果不可用)可用带有SELECT ... UNION ... SELECT的子查询替换。尽管想知道CROSS JOIN的性能...

– Cristi S.
18-10-16在20:39



#3 楼

使用交叉联接的另一种方法是在交叉联接内指定列名称。

select name, Subject, Marks 
from studentmarks
Cross Join (
values (Maths,'Maths'),(Science,'Science'),(English,'English')
) un(Marks, Subject)
where marks is not null;


#4 楼

选择*来自学生

UNPIVOT(标记为(数学,科学,英语)科目的科目);

评论


这已经和将近6年前发布的广受好评的答案是一样的答案吗?

– ImaginaryHuman072889
19年7月10日在12:34