Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL:UN-PIVOT并按单个分数分开_Sql_Sql Server_Sql Server 2008_Unpivot - Fatal编程技术网

SQL:UN-PIVOT并按单个分数分开

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

我正在使用SQLServer2008,并试图编写一个将列拆分为单独行的查询。我正在提取计数数据,需要将其转换为个人分数

例如: 5名学生回答“总是”,回答“总是”=3分; 4名学生回答“通常”,回答“通常”=2分

我希望有一个名为“Score”的字段,其中5行为3,4行为2,而不是一个名为“always”的字段,该字段的计数为5,而名为“通常”的字段的计数为4

我已经使用UNPIVOT开始了我的查询,但是,它并没有按照描述分割数据。我在下面提供了样本数据和我想要的结果。任何帮助都将不胜感激

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 |
+----------+---------+------------+-------+-----------+