SQL Server查找类先决条件循环

SQL Server查找类先决条件循环,sql,sql-server,tsql,sql-function,Sql,Sql Server,Tsql,Sql Function,堆栈溢出的人们好 我被SQL作业的最后一个问题困住了,需要指导 create table PREQUISITE ( Cno varchar(9) REFERENCES COURSE(Cno), Cpre varchar(9) REFERENCES COURSE(Cno), primary key(Cno, Cpre) ); 我有这个表,其中包含以下值: ('MATH 1910', 'MATH 1730'), ('CSCI 1170', 'MATH 1

堆栈溢出的人们好

我被SQL作业的最后一个问题困住了,需要指导

create table PREQUISITE (  
    Cno     varchar(9) REFERENCES COURSE(Cno), 
    Cpre    varchar(9) REFERENCES COURSE(Cno),
    primary key(Cno, Cpre)
);
我有这个表,其中包含以下值:

('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');
我试图用一个参数编写一个函数,例如
csci4700
,它返回一个包含类的所有先决条件以及这些类的先决条件等的字符串。我曾尝试使用滚动光标在表格中循环并重置回表格顶部,以及使用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

这里不需要在代码中寻找答案,只需要建议SQL操作可以实现这一点。下面的查询提供了树状结构。如果有循环引用,查询将挂起。例如,此代码不处理
代数->数学->代数
案例

src | req | lvl --: | ---: | --: 1 | 3 | 0 3 | 4 | 1 4 |空| 2 4 | 2 | 2 2 | 5 | 3 5 | 6 | 4 6 |空| 5
dbfiddle

这里是一个递归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;
返回:

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

欢迎来到SO!当询问SQL时,您可以轻松地将DBMS添加为标记,例如。还要注意正确的代码格式,因为这确实有助于阅读和发现问题。不要害羞,发布您的试用代码(
使用滚动光标循环
),这样我们就可以使用它。您可以使用递归公共表表达式。谢谢你们的回答,我没有听说过递归公共表表达式,我相信我已经为我的任务做了一件工作。再次感谢你
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;
CpreList
COMM 2200, CSCI 1170, CSCI 2170, CSCI 3080, CSCI 3110, MATH 1730, MATH 1910