SQL:UN-PIVOT并按单个分数分开
我正在使用SQLServer2008,并试图编写一个将列拆分为单独行的查询。我正在提取计数数据,需要将其转换为个人分数 例如: 5名学生回答“总是”,回答“总是”=3分; 4名学生回答“通常”,回答“通常”=2分 我希望有一个名为“Score”的字段,其中5行为3,4行为2,而不是一个名为“always”的字段,该字段的计数为5,而名为“通常”的字段的计数为4 我已经使用UNPIVOT开始了我的查询,但是,它并没有按照描述分割数据。我在下面提供了样本数据和我想要的结果。任何帮助都将不胜感激SQL:UN-PIVOT并按单个分数分开,sql,sql-server,sql-server-2008,unpivot,Sql,Sql Server,Sql Server 2008,Unpivot,我正在使用SQLServer2008,并试图编写一个将列拆分为单独行的查询。我正在提取计数数据,需要将其转换为个人分数 例如: 5名学生回答“总是”,回答“总是”=3分; 4名学生回答“通常”,回答“通常”=2分 我希望有一个名为“Score”的字段,其中5行为3,4行为2,而不是一个名为“always”的字段,该字段的计数为5,而名为“通常”的字段的计数为4 我已经使用UNPIVOT开始了我的查询,但是,它并没有按照描述分割数据。我在下面提供了样本数据和我想要的结果。任何帮助都将不胜感激 Al
Always = 3 points
Usually = 2 points
Sometimes = 1 points
Never = 0 points
样本数据:
查询:
预期结果:前2行
如果要取消PIVOT的列数可以管理,我通常只对每个列进行单独的查询,并结合UNION ALL 以下是总体思路:
SELECT Question, Student, StartDate, Always AS Score
FROM #TEST
WHERE ...
UNION ALL
SELECT Question, Student, StartDate, Usually AS Score
FROM #TEST
WHERE ...
在交叉申请和特别理货表的帮助下
Select A.Question
,A.Student
,A.StartDate
,B.Score
From #Test A
Cross Apply ( values (Always,3)
,(Usually,2)
,(Sometimes,1)
,(Never,0)
) B(Cnt,Score)
Join (Select Top 100 N=Row_Number() Over (Order By Number) From master..spt_values ) C
on (C.N <= B.Cnt)
Where Student='Bob' and question ='A'
使用交叉应用值。。。要取消填充数据、1-9的数字表和点表,我们可以执行以下操作:
with a as (
select *
from #test
where question = 'A'
and student = 'bob'
--and student in ('bob','jim')
--and startdate = '20160101'
)
, points as (
select Answer, Points
from (values ('Always',3),('Usually',2),('Sometimes',1),('Never',0)
) p (Answer,Points)
)
, numbers as (
select n
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9)
) t(n)
)
, unp as (
select
a.question
, a.student
, StartDate=convert(varchar(10),a.startdate,120)
, x.AnswerCount
, x.Answer
from a
cross apply (
values ([Always],'Always')
, ([Usually],'Usually')
, ([Sometimes],'Sometimes')
, ([Never],'Never')
) x (AnswerCount,Answer)
)
select
unp.question
, unp.student
, unp.startdate
, score = p.points
, unp.answer
from unp
inner join numbers n on n.n<=unp.AnswerCount
inner join points p on unp.answer=p.answer
感谢您的帮助,您的建议适用于我的示例数据集。您能解释一下这个连接吗?选择TOP 100 N=行数,而不是主..spt_值中的按编号排序?我从未见过使用此表,也不理解您为什么使用它或选择前100名。@JBritton只是创建了一个包含100条记录的临时计数/数字表。这将允许扩展您的记录集。@JBritton前100名是任意值。如果你看到的答案永远不会超过10个,那么就把它列为前10名。拥有更大的价值并没有坏处。子查询被解析一次
SELECT Question, Student, StartDate, Always AS Score
FROM #TEST
WHERE ...
UNION ALL
SELECT Question, Student, StartDate, Usually AS Score
FROM #TEST
WHERE ...
Select A.Question
,A.Student
,A.StartDate
,B.Score
From #Test A
Cross Apply ( values (Always,3)
,(Usually,2)
,(Sometimes,1)
,(Never,0)
) B(Cnt,Score)
Join (Select Top 100 N=Row_Number() Over (Order By Number) From master..spt_values ) C
on (C.N <= B.Cnt)
Where Student='Bob' and question ='A'
Question Student StartDate Score
A BOB 2016-01-01 3
A BOB 2016-01-01 3
A BOB 2016-01-01 2
A BOB 2016-01-01 1
A BOB 2016-01-01 0
A BOB 2016-01-01 0
A BOB 2016-03-01 3
A BOB 2016-03-01 3
A BOB 2016-03-01 3
A BOB 2016-03-01 2
A BOB 2016-03-01 1
with a as (
select *
from #test
where question = 'A'
and student = 'bob'
--and student in ('bob','jim')
--and startdate = '20160101'
)
, points as (
select Answer, Points
from (values ('Always',3),('Usually',2),('Sometimes',1),('Never',0)
) p (Answer,Points)
)
, numbers as (
select n
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9)
) t(n)
)
, unp as (
select
a.question
, a.student
, StartDate=convert(varchar(10),a.startdate,120)
, x.AnswerCount
, x.Answer
from a
cross apply (
values ([Always],'Always')
, ([Usually],'Usually')
, ([Sometimes],'Sometimes')
, ([Never],'Never')
) x (AnswerCount,Answer)
)
select
unp.question
, unp.student
, unp.startdate
, score = p.points
, unp.answer
from unp
inner join numbers n on n.n<=unp.AnswerCount
inner join points p on unp.answer=p.answer
+----------+---------+------------+-------+-----------+
| question | student | startdate | score | answer |
+----------+---------+------------+-------+-----------+
| A | bob | 2016-01-01 | 3 | Always |
| A | bob | 2016-01-01 | 3 | Always |
| A | bob | 2016-01-01 | 2 | Usually |
| A | bob | 2016-01-01 | 1 | Sometimes |
| A | bob | 2016-01-01 | 0 | Never |
| A | bob | 2016-01-01 | 0 | Never |
| A | bob | 2016-01-03 | 3 | Always |
| A | bob | 2016-01-03 | 3 | Always |
| A | bob | 2016-01-03 | 3 | Always |
| A | bob | 2016-01-03 | 2 | Usually |
| A | bob | 2016-01-03 | 1 | Sometimes |
+----------+---------+------------+-------+-----------+