0

我有一张如下表

studentID Subject
   1       Sub1
   2       Sub1
   3       Sub1
   4       Sub1
   1       Sub2
   2       Sub2
   4       Sub2
   1       Sub3
   3       Sub3
   4       Sub3

我需要对具有相同主题集的学生进行分组。只需为具有相同主题集的学生提供一个唯一的组 ID。

所以这里的学生 id (1) 和 (4) 会说 group id = 1

学生 id 2 - 组 id = 2(没有其他人只有 sub 1 和 sub 2)

学生 ID 3 - 组 ID = 3

结果应该像

 studentid groupid
     1        1
     4        1
     2        2
     3        3

我编写了一个 sqlquery,它使用 FORXML 将学生的所有科目分组到单个列,然后在该列上使用 group by,然后将排名与它们相关联。有一个更好的方法吗

4

2 回答 2

1

这是一种方法。

对于每个学生,找到具有相同课程集的所有其他学生。您可以使用以下规则来执行此操作。两个学生有相同的课程(1)他们每个人的课程数量相同;(2)他们共有的课程数量与课程数量相同。

该实现使用排名函数来查找课程数量和加入/分组依据来计算两个不同学生的共同数量。

之后,组 id 就是此表中的对中的最小学生 id。

select s1.StudentId, MIN(SameAsStudentId) as groupid
from (select s1.StudentId as StudentId, s2.StudentId as SameAsStudentId
      from (select ss.*, COUNT(*) over (studentId) as NumSubjects
            from ss
           ) s1 join
           (select ss.*, COUNT(*) over (studentId) as NumSubjects
            from ss
           ) s2
           where s1.Subject = s2.Subject
      group by s1.StudentId, s2.StudentId
      having s1.NumSubjects = s2.NumSubjects and
             COUNT(*) = s1.NumSubjects
     ) t
group by StudentId   

如果您想要没有“漏洞”的 groupid,您可以包装一个dense_rank用于分配组 id 的外部查询。

于 2012-11-19T15:54:02.107 回答
0

处理此问题的一种方法是为主题创建位掩码。首先为每个主题分配不同的、任意的 2 次幂:

Subject  Value
Sub1         1
Sub2         2
Sub3         4

现在您可以对每个学生的科目值求和。每个科目组合都将具有独特的价值。需要注意的是,如果主题数量太大,您可能会遇到数字溢出。

您甚至可以在单个查询中执行此操作:

Select StudentID, sum(Subject_Value)
from Student_Subjects ss join
     (select distinct subject, 
                      power(2,dense_rank() 
                              over (order by subject)-1) as Subject_Value 
      from Student_Subjects) sv 
  on ss.subject = sv.subject
group by StudentID
于 2012-11-19T16:14:16.060 回答