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,你的桌子结构似乎很有问题,也很有限。您可能应该重新设计您的数据库,并理解您的数据库设计应该涵盖未来的需求,而不仅仅是当前的需求。例如,如果你的学生有不止一个地址怎么办?这是一种非常常见的情况,您没有涵盖。您应该考虑关系数据库结构的基础知识(表之间的关系)。例如,地址可能应该在单独的表中,以允许您具有单对多关系(表中的其他信息也是如此)。您的请求我不清楚。请提供示例数据(查询以向表中插入一些行),并根据示例数据解释您的预期结果-您希望从特定的示例数据中得到什么。尽量提供涵盖所有场景的示例数据,以便我们能够讨论所有选项并提供完整的解决方案