Tsql 使用最新记录取消Pivot列
更新科目和更新日期的学生记录。学生可以注册一个或多个科目。我想得到每个学生的最新科目更新日期和状态记录Tsql 使用最新记录取消Pivot列,tsql,Tsql,更新科目和更新日期的学生记录。学生可以注册一个或多个科目。我想得到每个学生的最新科目更新日期和状态记录 CREATE TABLE Student ( StudentID int, FirstName varchar(100), LastName varchar(100), FullAddress varchar(100), CityState varchar(100), MathSta
CREATE TABLE Student
(
StudentID int,
FirstName varchar(100),
LastName varchar(100),
FullAddress varchar(100),
CityState varchar(100),
MathStatus varchar(100),
MUpdateDate datetime2,
ScienceStatus varchar(100),
SUpdateDate datetime2,
EnglishStatus varchar(100),
EUpdateDate datetime2
);
想要查询输出,我使用CTE方法,但试图找到替代和更好的方法
SELECT StudentID, FirstName, LastName, FullAddress, CityState, [SubjectStatus], UpdateDate
FROM Student
;WITH orginal AS
(SELECT * FROM Student)
,Math as
(
SELECT DISTINCT StudentID, FirstName, LastName, FullAddress, CityState,
ROW_NUMBER OVER (PARTITION BY StudentID, MathStatus ORDER BY MUpdateDate DESC) as rn
, _o.MathStatus as SubjectStatus, _o.MupdateDate as UpdateDate
FROM original as o
left join orignal as _o on o.StudentID = _o.StudentID
where _o.MathStatus is not null and _o.MUpdateDate is not null
)
,Science AS
(
...--Same as Math
)
,English AS
(
...--Same As Math
)
SELECT * FROM Math WHERE rn = 1
UNION
SELECT * FROM Science WHERE rn = 1
UNION
SELECT * FROM English WHERE rn = 1
第一:不建议以非规范化形式存储数据。一些数据模型的重新设计可能是正确的。web上有多种关于数据规范化的资源,如 现在,我根据您编写的查询猜测了如何填充源表。我生成了一些示例数据,可以显示如何创建源数据。此外,我还减少了列的数量,以减少我的打字工作。一般做法应该仍然有效 样本数据
create table Student
(
StudentId int,
StudentName varchar(15),
MathStat varchar(5),
MathDate date,
ScienceStat varchar(5),
ScienceDate date
);
insert into Student (StudentID, StudentName, MathStat, MathDate, ScienceStat, ScienceDate) values
(1, 'John Smith', 'A', '2020-01-01', 'B', '2020-05-01'),
(1, 'John Smith', 'A', '2020-01-01', 'B+', '2020-06-01'), -- B for Science was updated to B+ month later
(2, 'Peter Parker', 'F', '2020-01-01', 'A', '2020-05-01'),
(2, 'Peter Parker', 'A+', '2020-03-01', 'A', '2020-05-01'), -- Spider-Man would never fail Math, fixed...
(3, 'Tom Holland', null, null, 'A', '2020-05-01'),
(3, 'Tom Holland', 'A-', '2020-07-01', 'A', '2020-05-01'); -- Tom was sick for Math, but got a second chance
解决方案
您的问题标题已包含unpivot一词。这个词实际上作为关键字存在于T-SQL中。您可以在中了解unpivot
关键字。您自己的解决方案已经包含了常见的表表达式,这些构造应该看起来很熟悉
步骤:
cte_unpivot
=取消pivot所有行,创建一个Subject
列,并将相应的值(SubjectStat
,Date
)与case
表达式一起放置在其旁边cte\u recent
=对行进行编号,以查找每个学生和科目的最新行with cte_unpivot as
(
select up.StudentId,
up.StudentName,
case up.[Subject]
when 'MathStat' then 'Math'
when 'ScienceStat' then 'Science'
end as [Subject],
up.SubjectStat,
case up.[Subject]
when 'MathStat' then up.MathDate
when 'ScienceStat' then up.ScienceDate
end as [Date]
from Student s
unpivot ([SubjectStat] for [Subject] in ([MathStat], [ScienceStat])) up
),
cte_recent as
(
select cu.StudentId, cu.StudentName, cu.[Subject], cu.SubjectStat, cu.[Date],
row_number() over (partition by cu.StudentId, cu.[Subject] order by cu.[Date] desc) as [RowNum]
from cte_unpivot cu
)
select cr.StudentId, cr.StudentName, cr.[Subject], cr.SubjectStat, cr.[Date]
from cte_recent cr
where cr.RowNum = 1;
结果
StudentId StudentName Subject SubjectStat Date
----------- --------------- ------- ----------- ----------
1 John Smith Math A 2020-01-01
1 John Smith Science B+ 2020-06-01
2 Peter Parker Math A+ 2020-03-01
2 Peter Parker Science A 2020-05-01
3 Tom Holland Math A- 2020-07-01
3 Tom Holland Science A 2020-05-01
你好@Justin,你的桌子结构似乎很有问题,也很有限。您可能应该重新设计您的数据库,并理解您的数据库设计应该涵盖未来的需求,而不仅仅是当前的需求。例如,如果你的学生有不止一个地址怎么办?这是一种非常常见的情况,您没有涵盖。您应该考虑关系数据库结构的基础知识(表之间的关系)。例如,地址可能应该在单独的表中,以允许您具有单对多关系(表中的其他信息也是如此)。您的请求我不清楚。请提供示例数据(查询以向表中插入一些行),并根据示例数据解释您的预期结果-您希望从特定的示例数据中得到什么。尽量提供涵盖所有场景的示例数据,以便我们能够讨论所有选项并提供完整的解决方案