很抱歉,如果这是重复的地方,请在此处搜索,网络似乎与我的问题相似但不完全匹配,因此我决定发布。
我称其为多对多关系中的完全递归分组。我已经尝试编写联接和ctes来做到这一点,但是没有完全递归,我只能深入一层,而对于编写嵌套的动态游标我也不感到很兴奋。
可以从此“交界处”表派生假设表达式以查找不同的学生/班级,因此可以仅使用一组来总结问题。
SELECT * FROM student_class
+-------------+----------+--------------+
| student_id | class_id | group_number |
+-------------+----------+--------------+
| 1 | A | null |
| 1 | C | null |
| 2 | A | null |
| 2 | B | null |
| 2 | C | null |
| 3 | E | null |
| 4 | B | null |
| 4 | F | null |
+-------------+----------+--------------+
问题是如何通过递归关系为每个学生和每个班级填充组号。例如:如果student_id 1具有class_id A,那么还有哪些其他学生具有class_id A?对于其他学生,他们还开设哪些其他课程?对于其他每个班级,其他哪些学生也有这些班级?然后继续遍历结果,直到找不到更多依赖项为止。
因此,在此示例中,最终更新将仅包含两个组,因此应这样读取,因为没有其他学生拥有class_id C,student_id 3没有其他班级:
+-------------+----------+--------------+
| student_id | class_id | group_number |
+-------------+----------+--------------+
| 1 | A | 1 |
| 1 | C | 1 |
| 2 | A | 1 |
| 2 | B | 1 |
| 2 | C | 1 |
| 3 | E | 2 |
| 4 | B | 1 |
| 4 | F | 1 |
+-------------+----------+--------------+
答案 0 :(得分:0)
这真的很棘手。这是一种图形遍历算法(并不难)。但是您必须定义图。您可以使用自连接定义两个类之间的链接。然后可以将其用于递归CTE。
因此,要获得等价类(此处有点挑剔),您可以这样做:
with cs as (
select *
from (values (1, 'A'), (1, 'C'), (2, 'A'), (2, 'B'), (2, 'C'), (3, 'E'), (4, 'B'), (4, 'F')) v(student, class)
),
cc as (
select distinct cs1.class as class1, cs2.class as class2
from cs cs1 join
cs cs2
on cs1.student = cs2.student
),
cte as (
select cc.class1 as class, cc.class2 as grp, cast(',' + cc.class1 + ',' as varchar(max)) as grps
from cc
union all
select cte.class, cc.class2,
cast(grps + cc.class2 + ',' as varchar(max)) as grps
from cte join
cc
on cc.class1 = cte.grp and cte.grps not like '%,' + cc.class1 + ',%'
)
select cte.class, min(cte.grp)
from cte
group by cte.class;
如果要将它们转换为数字:
select cte.class, min(cte.grp),
dense_rank() over (order by min(cte_grp)) as group_number
from cte
group by cte.class;