使用列名取消透视
Posted
技术标签:
【中文标题】使用列名取消透视【英文标题】:Unpivot with column name 【发布时间】:2013-10-04 01:18:28 【问题描述】:我有一张表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
使用unpivot,我能够正确获取名称、标记,但无法将源表中的列名获取到所需结果集中的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 with demo
【讨论】:
@bluefeet 有没有一种方法可以让您无需指定名称(数学、科学、英语)?我正在对许多表执行此操作,所有表都具有相同的结构但具有不同的列名。 @LBogaardt 不,您需要明确定义要包含的列。 @LBogaardt 看看我的回答here,您可以使用动态 sql 来取消透视,而无需指定列名。【参考方案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! VALUES,当不可用时,可以用带有 SELECT ... UNION ... SELECT ... 的子查询替换 ... 想知道 CROSS JOIN 的性能...【参考方案3】:使用交叉连接的另一种方法是在交叉连接中指定列名
select name, Subject, Marks
from studentmarks
Cross Join (
values (Maths,'Maths'),(Science,'Science'),(English,'English')
) un(Marks, Subject)
where marks is not null;
【讨论】:
以上是关于使用列名取消透视的主要内容,如果未能解决你的问题,请参考以下文章