Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从2个外键生成所有可能的组合_Sql_Sql Server_Sql Server 2014 - Fatal编程技术网

Sql 从2个外键生成所有可能的组合

Sql 从2个外键生成所有可能的组合,sql,sql-server,sql-server-2014,Sql,Sql Server,Sql Server 2014,我正在使用Microsoft SQL Server 2014 假设我有一个包含3个表的大学数据库。一个列出课程,一个列出年份,一个列出可以做的课程 CREATE TABLE Courses ( Course_ID varchar(5) PRIMARY KEY NOT NULL, Name varchar(255) NOT NULL ) CREATE TABLE Years ( Year_ID tinyint ) CREATE TABLE Coursework (

我正在使用Microsoft SQL Server 2014

假设我有一个包含3个表的大学数据库。一个列出课程,一个列出年份,一个列出可以做的课程

CREATE TABLE Courses (
    Course_ID varchar(5) PRIMARY KEY NOT NULL,
    Name varchar(255) NOT NULL
)

CREATE TABLE Years (
    Year_ID tinyint
)

CREATE TABLE Coursework (
    CW_ID varchar(5) PRIMARY KEY NOT NULL,
    Name varchar(255) NOT NULL,
    Allowed varchar(255) NOT NULL
)
现在,课程作业可以是任何课程/年的组合。所以,我可以有一个课程作业,专门允许学生在第一年学习X课程,另一个允许学生在第二年和第三年学习X课程,Y课程和Z课程,一个允许学生在所有年份学习X课程,一个允许学生在第一年和第二年学习任何课程,甚至一个允许所有课程和所有年份。(我希望我的观点能被理解。)

“允许”将验证组合是否有效,可以通过引用每个表(课程和年份)的外键进行验证

但是我该怎么做呢?我曾考虑过使用复合主键创建一个新表,但这需要手动输入,并且仅限于成对的组合

所以我的猜测是,我需要以某种方式生成可能的组合,将它们列在一个表中,每个表都有一个唯一的主键,并将其作为外键引用到“课程作业”表中。然而,我有点卡住了。有什么建议吗

编辑:

要澄清我想要什么:

想象一下下表:

Course_ID    Name

A            Arithmetics
B            Biology
C            Chemistry
以及以下年份表:

Year_ID

1
2
3
现在,一位老师创造了一个新的课程。他们希望在第二年或第三年将其提供给学习生物或化学的学生。因此,在第三年学习生物学的人、在第二年学习化学的人都可以使用,但在第一年学习生物学的人或在第二年学习算术的人却不能使用

他们会将课程作业插入表格中

CW_ID    Name             Allowed

SA       Soil analysis    B,C,2,3
这很好,但我如何检查他们输入的值是否存在,以阻止他们输入“X,5”,例如,因为课程/年不存在

编辑2:

我在测试一些东西,但除此之外,它肯定不是最好的解决方案,我甚至不知道如何实现它

CREATE TABLE YesOrNo (
    YesOrNo_ID bit PRIMARY KEY NOT NULL
)

CREATE TABLE Allowed (
    Allowed_ID int IDENTITY(1,1),
    Arithmetics bit FOREIGN KEY REFERENCES YesOrNo(YesOrNo_ID) NOT NULL,
    Biology bit FOREIGN KEY REFERENCES YesOrNo(YesOrNo_ID) NOT NULL,
    Chemistry bit FOREIGN KEY REFERENCES YesOrNo(YesOrNo_ID) NOT NULL,
    First bit FOREIGN KEY REFERENCES YesOrNo(YesOrNo_ID) NOT NULL,
    Second bit FOREIGN KEY REFERENCES YesOrNo(YesOrNo_ID) NOT NULL,
    Third bit FOREIGN KEY REFERENCES YesOrNo(YesOrNo_ID) NOT NULL
)
通过将所有课程/学年中的1和0的所有组合(真或假)填入允许的表格,教师只需在课程作业表格中插入允许的\u ID,就可以知道课程作业允许的课程/学年

然而,手动添加所有课程和年份作为属性是不切实际的,即使这样,我也不知道如何自动填充表中所有的可能性

从示例中可以看出,表中的一行如下所示:

Allowed_ID    Arithmetics    Biology    Chemistry    First    Second    Third

42            0              1          1            0        1         1

教师只需在课程作业表的允许字段中输入“42”。

您需要一个多对多联接表,而不是一列,来记录哪些作业对哪些课程和年份有效

CREATE TABLE ValidCourseworkByYear (
    VCWBY_ID int PRIMARY KEY IDENTITY(1,1),
    CW_ID varchar(5) NOT NULL,
    Course_ID varchar(5) NOT NULL,
    Year_ID tinyint NOT NULL
)
这在作品、课程和年份之间建立了联系,而不会重复数据或防止数据被多次使用。如果该表中不存在该条目,则该特定的工作课程年组合无效

如果你的课程作业表已经是课程的外键(这意味着一件作品只能在一门课程中使用),那么你可以从此表中删除CW_ID


另外,不要使用字符串作为主键;他们表现很差。如果您想要一个简短的标识符用于显示,请将其作为一个单独的列,并对其施加唯一的约束。

作为一次性交易,您可以执行以下操作:

insert into Coursework (
    Course_ID ,
    Year_ID )
select
    Courses.Course_ID ,
    Years.YearID
from
    Courses
cross join
    Years
如果您想变得更花哨&而不是添加重复项:

insert into Coursework (
    Course_ID ,
    Year_ID )
select
    Courses.Course_ID ,
    Years.Year_ID
from
    Courses
cross join
    Years
left join
    Coursework
on
    Courses.Course_ID = Coursework.Course_ID
and
    Years.Year_ID = Coursework.Year_ID
where
    Courses.CW_ID is null

我很难理解你在这里想要实现什么。如果您想要的只是一个基于不同表中键值的所有可能组合的列表,那么您可以通过
交叉连接来实现这一点?即使每个表中只有少量行,组合的数量也会惊人。你到底想在这里做什么,我们可以帮助你找到更好的方法。你为什么不先问谷歌?我只需要这个属性来确定哪些学生可以学习这些课程(什么课程,什么年份)。我现在意识到,生成所有可能的组合可能不是最好的解决方案,但我似乎无法确定另一个…另外,我只是做了交叉连接,但这毕竟不是我真正需要的,因为它只是列出了所有年份的所有课程。我想要的是在表格中选择或存储可供选择的课程和年份。类似于:(X,Y,Z,1,2,3)或(X,1,2,3)或(X,Y,1)如何将实际信息添加到该表中?这只是建立了关系,对吗?是的,模式定义只是定义了关系。填充联接表的精确机制取决于是将新数据插入到其他表中,还是为现有数据记录此关系。无论如何,年份、课程和工作数据都需要先放在各自的表中,这样您就可以将主键插入到联接表中。您可以填充这些表,编写一个select查询以获取相应关系的键,然后将结果插入到联接表中。当我将其粘贴到SQLFIDLE中时,它会显示“无效的列名'Course_ID'。知道为什么吗?没关系,我必须将课程ID和年份ID作为属性添加到课程作业表中。。。但是,这并不能完全解决问题。首先,课程作业已经填充了CW_ID和名称,这将忽略这一点。但是,即使我将所有这些都放在一个单独的表中(例如ValidCourseworkByYear),我如何声明课程作业适用于所有课程和所有年份?或者在第一年和第二年,当然是X年,或者其他的。事实上,它只是说明课程/年数的组合(X,1)(X,2)(X,3)(Y,1)(Y,2)(Y,3)等,而不是(X,Y,1,2)等