你有相当执行任务,但归该表是做正确的事。在旧表格的示例中,我注意到您已经重复了[StartDate] & [EndDate]。 这在SQL Sever中不可行,所有列名在表中必须是唯一的。我希望这只是样品中的一个小故障,因为它会变得非常重要。
下面我使用一种方法来将学生行“转移”为多个较短的行,这代表了实现您的目标的临时步骤。该方法使用CROSS APPLY
和VALUES
。请注意,您需要手动准备这个VALUES
部分,但是您可能能够从查询中获取针对您的信息架构的字段列表(未提供此查询)。
在SQL Fiddle
MS SQL服务器2014架构设置见的这样的工作模式:
CREATE TABLE Student
([St_id] int, [St_Name] varchar(1), [St_University] varchar(1)
, [SoftSkillTraining] varchar(4), [StartDate1] datetime, [EndDate1] datetime
, [ComputerTraining] varchar(5), [StartDate2] datetime, [EndDate2] datetime)
;
INSERT INTO Student
([St_id], [St_Name], [St_University]
, [SoftSkillTraining], [StartDate1], [EndDate1]
, [ComputerTraining], [StartDate2], [EndDate2])
VALUES
(1, 'x', 'x', 'True', '2017-02-12 00:00:00', '2017-03-12 00:00:00', 'False', NULL, NULL),
(2, 'y', 'x', 'True', '2016-05-25 00:00:00', '2016-06-25 00:00:00', 'True', '2017-08-01', NULL)
;
这是最重要的查询它 “unpivots” 源数据多行
请注意如何为每个培训课程分配一个id,以及column groups
如[SoftSkillTraining], [StartDate1], [EndDate1]
必须是在值区域中逐行指定。这里的每一行都会产生一个新的输出行,因此值区域的“布局”基本上决定了最终输出的结果。在这个区域,您需要仔细收集所有列名并准确安排。
select
St_id, ca.TrainingId, ca.TrainingName, ca.isEnrolled, ca.StartDate, ca.EndDate
into training_setup
from Student
cross apply (
values
(1, 'SoftSkillTraining', [SoftSkillTraining], [StartDate1], [EndDate1])
,(2, 'ComputerTraining', [ComputerTraining], [StartDate2], [EndDate2])
) ca (TrainingId,TrainingName,isEnrolled, StartDate,EndDate)
where ca.isEnrolled = 'True'
;
查询2:
select
*
from training_setup
Results:
| St_id | TrainingId | TrainingName | isEnrolled | StartDate | EndDate |
|-------|------------|-------------------|------------|----------------------|----------------------|
| 1 | 1 | SoftSkillTraining | True | 2017-02-12T00:00:00Z | 2017-03-12T00:00:00Z |
| 2 | 1 | SoftSkillTraining | True | 2016-05-25T00:00:00Z | 2016-06-25T00:00:00Z |
| 2 | 2 | ComputerTraining | True | 2017-08-01T00:00:00Z | (null) |
查询3:
-- this can be the basis for table [Training]
select distinct TrainingId,TrainingName, StartDate,EndDate
from training_setup
Results:
| TrainingId | TrainingName | StartDate | EndDate |
|------------|-------------------|----------------------|----------------------|
| 1 | SoftSkillTraining | 2016-05-25T00:00:00Z | 2016-06-25T00:00:00Z |
| 1 | SoftSkillTraining | 2017-02-12T00:00:00Z | 2017-03-12T00:00:00Z |
| 2 | ComputerTraining | 2017-08-01T00:00:00Z | (null) |
注意我对这个数据的一致性保留,注意开始/结束日期为一个疗程不同。我没有一个简单的解决方案。您可能需要清理数据以最大限度地减少差异,并且/或者您可能需要额外的步骤,使其与我们在交叉应用中使用的ID匹配,再加上开始/结束日期对,以更新training_id来获得更好的版本training_setup临时表,然后再继续。
查询4:
-- this can be the basis for table [Student_Training]
select St_id, TrainingId
from training_setup
Results:
| St_id | TrainingId |
|-------|------------|
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
你在这3代表期待什么列?你有没有试过你自己的任何疑问? –
我编辑了这个问题来进一步解释列。我尝试了一些查询,但没有工作。 –
“培训地点”从哪里来?它没有显示在退出学生表的示例中。 –