2017-10-09 155 views
1

如果能够帮助我解决以下问题,我将不胜感激。 这是一个非标准化,简化了我的数据集模型。它显示学生会议。每个学生每次可能有0,1或2个同学。 我想从这里去:SQL Server数据透视表。动态创建分组

SessionID StudentID Name LastName CoStudent 
------------------------------------------------------------------ 
123   112   John Smith  Mary Henderson 
123   112   John Smith  Chris Jameson 
456   571   Panos Kotsos  NULL 
510   95   Adam Jones  Ed Stevenson 
850   56   Ed  Stevenson Adam Jones 
160   401   Mary Henderson John Smith 
160   401   Mary Henderson Lucy Smith 

..to这里:

SessionID StudentID Name LastName CoStudent1  CoStudent2  NumOfCoStudnts 
--------------------------------------------------------------------------------------- 
123   112   John Smith  Mary Henderson Chris Jameson 2 
160   401   Mary Henderson John Smith  Lucy Smith  2 
456   571   Panos Kotsos  NULL   NULL   0 
510   95   Adam Jones  Ed Stevenson NULL   1 
850   56   Ed  Stevenson Adam Jones  NULL   1 

我认为这可以使用PIVOT查询来完成。问题是我实现这一目标的唯一方法是对一个额外的列进行硬编码:CoStud1_2(值'CoStudent1','CoStudent2')。 我可以在不添加额外列的情况下实现相同的结果,或者至少在运行时创建额外的列吗?

谢谢。

Chris。

DECLARE @STUDENTS TABLE 
    ( 
    sessionid   INT, 
    studentid   INT, 
    NAME    VARCHAR(100), 
    lastname   VARCHAR(100), 
    costud1_2   VARCHAR(100), 
    numberofcostudents VARCHAR(100) 
) 
INSERT INTO @STUDENTS 
VALUES 
    (123,112,'John','Smith','Mary Henderson', 'CoStudent1'), 
    (123,112,'John','Smith','Chris Jameson', 'CoStudent2'), 
    (456,571,'Panos','Kotsos',NULL, NULL), 
    (510,95,'Adam','Jones','Ed Stevenson', 'CoStudent1'), 
    (850,56,'Ed','Stevenson','Adam Jones', 'CoStudent1'), 
    (160,401,'Mary','Henderson','John Smith', 'CoStudent1'), 
    (160,401,'Mary','Henderson','Lucy Smith', 'CoStudent2') 

SELECT *, 
     Count(costudent1) + Count(costudent2) AS NumberOfCoStudents 
FROM (-- Query goes here 
     SELECT * 
     FROM @STUDENTS) t 
     PIVOT (Max(costud1_2) 
      FOR numberofcostudents IN ([CoStudent1],[CoStudent2]))p 
GROUP BY p.sessionid, 
      p.studentid, 
      p.NAME, 
      p.lastname, 
      p.costudent1, 
      p.costudent2 

回答

0

YPU可以使用ROW_NUMBER来创建所需的联合学生1和2之间辨别这个额外的列然后使用有条件聚集获得所需要的结果:

;WITH CTE AS (
    SELECT sessionid, studentid, name, lastname, CoStudent, 
      ROW_NUMBER() OVER (PARTITION BY sessionid, studentid, name, lastname 
          ORDER BY CoStudent) AS rn 
    FROM @STUDENTS 
) 
SELECT sessionid, studentid, name, lastname, 
     MAX(CASE WHEN rn = 1 THEN CoStudent END) AS CoStudent1, 
     MAX(CASE WHEN rn = 2 THEN CoStudent END) AS CoStudent2, 
     COUNT(CoStudent) AS NumOfCoStudnts 
FROM CTE 
GROUP BY sessionid, studentid, name, lastname 

注:对于动态数量的联合学生,1,2,...,n,你必须使用动态sql。

Demo here

+0

非常感谢Giorgos。这是一个很好的方法!我注意到的唯一想法是,即使在记录中没有同学时,以下行返回1而不是0: COUNT(*)AS NumOfCoStudnts 当我将其更改为 时,我得到正确的结果COUNT(CoStudent)AS NumOfCoStudnts –

+0

@ChrisKotsiopoulos是的,这是一个很好的发现。 'COUNT(*)'统计属于该组的记录数,COUNT(CoStudent)'忽略空值,并且正确地记录联合学生的数量。 –