简体   繁体   English

SQL Server 查找类先决条件循环

[英]SQL Server Finding Class Prerequisites Loop

Hello people of Stack Overflow,你好 Stack Overflow 的人们,

I am stuck on the last question of my SQL assignment, and am in need of direction.我被困在 SQL 作业的最后一个问题上,需要指导。

create table PREQUISITE (  
    Cno     varchar(9) REFERENCES COURSE(Cno), 
    Cpre    varchar(9) REFERENCES COURSE(Cno),
    primary key(Cno, Cpre)
);

I have this table, with these values:我有这张表,具有以下值:

('MATH 1910', 'MATH 1730'),
('CSCI 1170', 'MATH 1730'),
('CSCI 2170', 'CSCI 1170'),
('CSCI 3080', 'CSCI 1170'),
('CSCI 3080', 'MATH 1910'),
('CSCI 3110', 'CSCI 2170'),
('CSCI 3110', 'CSCI 3080'),
('CSCI 3130', 'CSCI 2170'),
('CSCI 3210', 'CSCI 3110'),
('CSCI 3210', 'COMM 2200'),
('CSCI 3240', 'CSCI 2170'),
('CSCI 3240', 'CSCI 3130'),
('CSCI 4610', 'CSCI 3110'),
('CSCI 4610', 'CSCI 3130'),
('CSCI 4700', 'CSCI 3110'),
('CSCI 4700', 'COMM 2200');

I am trying to write a function with a single parameter, for instance CSCI 4700 that returns a string containing all of the class's prerequisites, as well as those class's prerequisites and so on.我正在尝试编写一个带有单个参数的函数,例如CSCI 4700 ,它返回一个包含所有类的先决条件的字符串,以及那些类的先决条件等等。 I have tried to use a scroll cursor to loop through the table and reset back to the top of the table as well as a while exists loop, but am unsure of which path to follow to generate this output:我曾尝试使用滚动光标循环遍历表格并重置回表格顶部以及 while exists 循环,但我不确定要遵循哪条路径来生成此输出:

CSCI 4700 -- CSCI 3110, COMM 2200 
CSCI 3110 --  CSCI 3080, 2170 
COMM 2200 -- no perquisite 
CSCI 3080 -- CSCI 1170, MATH 1910 
CSCI 2170 -- CSCI 1170 CSCI 1170 -- MATH 1730 
MATH 1910 -- MATH 1730  
MATH 1730 -- no prequisite

Not looking for answers in code here, just suggestions on what SQL operations could achieve this不是在这里寻找代码中的答案,只是关于哪些 SQL 操作可以实现此目的的建议

The following query gives tree-like structure.以下查询给出树状结构。 If you have circular references, the query will hang.如果您有循环引用,查询将挂起。 For example this code does not handle the ALGEBRA -> MATH -> ALGEBRA case.例如,此代码不处理ALGEBRA -> MATH -> ALGEBRA情况。

 with src as ( select 1 as id, 3 as req_id union all select 2 as id, 5 as req_id union all select 3 as id, 4 as req_id union all select 4 as id, null as req_id union all select 4 as id, 2 as req_id union all select 5 as id, 6 as req_id union all select 6 as id, null as req_id ), q0 as ( select * from src where id = 1 ), q1(src, req, lvl) as ( select id, req_id, 0 from q0 union all select id, req_id, lvl + 1 from src inner join q1 on req = id ) select * from q1 GO
 src |来源 | req |请求 | lvl --: |等级——: | ---: | ---: | --: 1 | --: 1 | 3 | 3 | 0 3 | 0 3 | 4 | 4 | 1 4 | 1 4 | null || 2 4 | 2 4 | 2 | 2 | 2 2 | 2 2 | 5 | 5 | 3 5 | 3 5 | 6 | 6 | 4 6 | 4 6 | null || 5 5个

db<>fiddle here db<> 在这里摆弄

Here's a recursive CTE with some string aggregation that might give you an idea for your function.这是一个带有一些字符串聚合的递归 CTE,可能会让您对您的函数有所了解。

DECLARE @Cno VARCHAR(9);
DECLARE @CpreList VARCHAR(4000);
SET @Cno = 'CSCI 4700';

WITH RCTE AS
(
    SELECT Cno AS BaseCno, 0 AS Lvl, Cno, Cpre
    FROM PREQUISITE
    WHERE Cno = @Cno

    UNION ALL

    SELECT c.BaseCno, Lvl+1, t.Cno, t.Cpre
    FROM RCTE c
    JOIN PREQUISITE t ON t.Cno = c.Cpre
    WHERE t.Cno != c.BaseCno
)
SELECT @CpreList = STRING_AGG(Cpre, ', ') WITHIN GROUP (ORDER BY Cpre)
FROM (SELECT DISTINCT BaseCno AS Cno, Cpre FROM RCTE) q
GROUP BY Cno;

SELECT @CpreList AS CpreList;

Returns:退货:

CpreList
COMM 2200, CSCI 1170, CSCI 2170, CSCI 3080, CSCI 3110, MATH 1730, MATH 1910

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM