如果是我,我会将其设计为 3 个数据流。
数据流 1 - 学生人数
由于我们假设姓名是学生独一无二的原因,因此我们需要建立一个独特姓名的大列表。
SELECT D.*
FROM
(
SELECT S.Student1 AS StudentName
FROM dbo.MyTable AS S
UNION
SELECT S.Student2 AS StudentName
FROM dbo.MyTable AS S
UNION
SELECT S.Student3 AS StudentName
FROM dbo.MyTable AS S
UNION
SELECT S.Student4 AS StudentName
FROM dbo.MyTable AS S
)D
WHERE D.StudentName IS NOT NULL
ORDER BY D.StudentName;
在查询中使用 UNION 将处理重复数据删除,我们将其包装在派生表中以过滤 NULL。
我添加了一个明确的顺序,但由于我假设您使用名称作为主键,所以我们在获取数据时避免排序操作。
将 OLE DB 源添加到您的数据流中,而不是在下拉列表中选择表,您将使用上述查询。
将 OLE DB 目标添加到同一数据流并连接两者。假设您的目标表看起来像
CREATE TABLE dbo.Student
(
StudentName varchar(50) NOT NULL CONSTRAINT PK__dbo__Student PRIMARY KEY(StudentName)
);
数据流 2 - 课程
此处选择经销商,您可以编写查询或直接指向源表。
使用 SSIS 的一个非常好的做法是只将您需要的数据带入缓冲区,因此我会编写一个类似的查询
SELECT DISTINCT S.[Lesson Id], S.[Lesson Name], S.[Lesson Duration]
FROM dbo.MyTable AS S;
我喜欢这里的独特之处,因为我对您的数据知之甚少,但如果它被扩展并且提供第二堂数学课来容纳另外 4 名学生,它可能又是第 1 课。或者它可能是 3,因为它表示课程时间或其他内容。
添加一个 OLE DB 目标并登陆数据。
数据流 3 - 多对多
有几种不同的方法来处理这个问题。我更喜欢懒惰的方式,并从第一个数据流开始重复我们的方法
SELECT D.*
FROM
(
SELECT S.Student1 AS StudentName, S.[Lesson Id]
FROM dbo.MyTable AS S
UNION
SELECT S.Student2 AS StudentName, S.[Lesson Id]
FROM dbo.MyTable AS S
UNION
SELECT S.Student3 AS StudentName, S.[Lesson Id]
FROM dbo.MyTable AS S
UNION
SELECT S.Student4 AS StudentName, S.[Lesson Id]
FROM dbo.MyTable AS S
)D
WHERE D.StudentName IS NOT NULL
ORDER BY D.StudentName;
然后使用 OLE DB 目标登陆您的桥接表并完成它。
如果这是让你学习原生组件的家庭作业/作业...
坚持使用 3 数据流方法。一次尝试做太多事情会带来麻烦。
将宽数据移动到窄数据的操作是Unpivot操作。你会在学生和桥表数据流中使用它,但老实说,我认为我在我的职业生涯中使用该组件的次数不到 10 次和/或在这里回答 SSIS 问题,我做了很多那个。
如果 Unpivot 操作生成 NULL,那么是的,您可能希望使用条件拆分来过滤掉这些行。
如果您的引用表更复杂,那么您可能会在桥接表填充步骤中添加一个查找组件来检索代理键。