Sql 从2个外键生成所有可能的组合
我正在使用Microsoft SQL Server 2014 假设我有一个包含3个表的大学数据库。一个列出课程,一个列出年份,一个列出可以做的课程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 (
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)等