根据另一个字段的最大值获取字段的第一个值,同时还使用其他最大值字段

Posted

技术标签:

【中文标题】根据另一个字段的最大值获取字段的第一个值,同时还使用其他最大值字段【英文标题】:get first value of a field based on the max of another field while other max fields are also being used 【发布时间】:2017-05-30 16:58:22 【问题描述】:

我正在使用多个 MAX 语句来获取学生的“最后一项活动”。学生每年入学都有一份入学记录。除了一个字段外,我得到了所有正确的结果。学生上一所学校的学校名称。最后一所学校可以通过获取保存最后入学日期的记录中的学校名称......但我似乎找不到解决方案,或者没有将代码放在正确的位置......或其他东西。我尝试过的不同方法是在底部缩进 cmets。 声明@grade char(2); 设置@grade='00'

Select 
SD.[Last_Name],
SD.[First_Name],
SD.[Middle_Name],
SD.[Name_Appendage] as [Name_Suffix],
convert(varchar,cast(SD.[DOB] as date),101) as [Date_Of_Birth],
SD.[Student_Number] as [Student_Number],
Max (SE.[Academic_Year]) as [Academic_Year],
Max (CONVERT(VARCHAR, SE.[Withdrawal_Date], 101)) as 
[Last_Withdrawal_Date],
Max (CONVERT(VARCHAR, SE.[Graduation_Date], 101)) as 
[Graduation_Date],
Max (SD.[DOE_Number]) as [State_Id],
Max (CONVERT(VARCHAR, SE.[Entry_Date], 101)) as [Last_Entry_Date],
Max (SE.[Graduation_Year]) as [Graduation_Year],
Max (CASE when SE.[Grade_Level] > '12' then @grade 
else SE.[Grade_Level]
End) as [Grade_Level]
From
Student_DemographicsCube as SD WITH (NOLOCK),
Student_EnrollmentCube as SE WITH (NOLOCK)
Where
SD.[Student_ID] = SE.[Student_ID] And
SE.[Entry_Date] > cast('12/31/2001' as date) And
SE.[School_Domain] in 
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,26,27,28,29,30,31)
Group By
SD.[Student_Number],
SD.[First_Name],
SD.[Middle_Name],
SD.[Last_Name],
SD.[Name_Appendage],
SD.[DOB]
Order By
SD.[Student_Number] asc,
Max (SE.[Entry_Date]) asc

最后一次注册学校名称的尝试解决方案

/* Select TOP (1) (SE.[School_Name]) from */
/*                Student_EnrollmentCube order by (SE.[Entry_Date) desc ) */
/* (Select SE.[School_Name] from Student_EnrollmentCube as */
/*        ST with (NOLOCK) where @holddate = SE.[Entry_Date]) */
/*SE.[School_Name] as [School_Name] */
/* Max (CASE when Max (SE.[Entry_Date]) = SE.[Entry_Date] */
/*                  then SE.[School_Name] */
/*                else @school */ 
/*            End) as [School_Name] */
/*      Select TOP (1) SE.[School_Name] from */
/*               Student_EnrollmentCube Group by SE.[Student_Number] */
/*                      order by SE.[Entry_Date] desc  */
/*ROW_NUMBER() OVER (PARTITION BY SE. */
/*           [Student_NUmber],SE.[Academic_Year] ORDER BY SD.*/
/*       [Student_Number],SE.[Academic_Year]) as seqnum */
/*               FROM SE.[Academic_Year] t */
/*             ) t */
/*           WHERE seqnum = 1; */ 


/*6/2/17 Code____________________________________________/*
DECLARE @grade char(2);
Set @grade='00'
Select 
SD.[Last_Name],
SD.[First_Name],
SD.[Middle_Name],
SD.[Name_Appendage] as [Name_Suffix],
    convert(varchar,cast(SD.[DOB] as date),101) as [Date_Of_Birth],
SD.[Student_Number] as [Student_Number],
     Max (SE.[Academic_Year]) as [Academic_Year],
convert(varchar,cast(w.[Last_Withdrawal_date] as date),101) as 
     [Latest_Withdrawal_Date] ,
convert(varchar,cast(g.[Last_Graduation_Date] as date),101) as 
     [Latest_Graduation_Date] ,
Max (SD.[DOE_Number]) as [State_Id],
Max (CONVERT(VARCHAR, e.[Entry_Date], 101)) as [Last_Entry_Date],
Max (SE.[Graduation_Year]) as [Graduation_Year],
Max (CASE when SE.[Grade_Level] > '12' then @grade 
     else SE.[Grade_Level]
     End) as [Grade_Level],
e.[School_Name]
From
Student_DemographicsCube SD WITH (NOLOCK),
Student_EnrollmentCube SE WITH (NOLOCK)
cross apply (select top 1 e.[School_Name], e.[Entry_Date] from 
    Student_EnrollmentCube e
    where e.[Student_id] = se.[Student_id] and se.[entry_date] > 
    cast('12/31/2001' as date) order by  e.[Student_ID], e.[Entry_Date] 
    desc) i
cross apply (select top 1 w.[Withdrawal_Date] as [Last_Withdrawal_Date] 
    from Student_EnrollmentCube w
    where w.[Student_id] = se.[Student_id] and se.[entry_date] > 
    cast('12/31/2001' as date) order by w.[Student_id], w.[Withdrawal_Date] 
    desc) w
cross apply (select top 1 g.[Graduation_Date] as [Last_Graduation_Date] 
    from Student_EnrollmentCube g
    where g.[Student_id] = se.[Student_id] and se.[entry_date] > 
    cast('12/31/2001' as date) order by g.[Student_id], g.[Graduation_Date] 
    desc) g

Where
SD.[Student_ID] = SE.[Student_ID] And sd.[student_Number] = 700010068 and
     SE.[Entry_Date] > cast('12/31/2001' as date) And
SE.[School_Domain] in 
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,13,24,25,26,27,28,29,30,31)

Group By
SD.[Student_Number],
SD.[First_Name],
SD.[Middle_Name],
SD.[Last_Name],
SD.[Name_Appendage],
SD.[DOB],
e.[school_name],
w.[Last_Withdrawal_Date],
g.[Last_Graduation_Date]

Order By
SD.[Student_Number] asc,
Max (SE.[Entry_Date]) asc

【问题讨论】:

【参考方案1】:

使用cross apply()Student_EnrollmentCube 获取最新的行以获取最新的入学日期和学校名称

declare @grade char(2);
set @grade = '00';

select
    sd.Last_Name
  , sd.First_Name
  , sd.Middle_Name
  , Name_Suffix            = sd.Name_Appendage
  , Date_Of_Birth          = convert(char(10), convert(date,sd.dob), 101)
  , Student_Number         = sd.Student_Number
  , Academic_Year          = max(se.Academic_Year)
  , Latest_Withdrawal_Date = convert(char(10), max(convert(date,se.Withdrawal_date)), 101)
  , Latest_Graduation_Date = convert(char(10), max(convert(date,se.Graduation_Date)), 101)
  , State_Id               = max(sd.doe_Number)
  , x.Last_Entry_Date        
  , x.School_Name            
  , Graduation_Year        = max(se.Graduation_Year)
  , Grade_Level            = case when max(try_convert(int,se.Grade_Level)) > 12 then @grade else se.Grade_Level end)
from Student_DemographicsCube sd
  inner join Student_EnrollmentCube se
    on sd.Student_id = se.Student_id
  cross apply (
     select top 1 
          i.School_Name
        , Last_Entry_Date = i.Entry_Date
     from Student_EnrollmentCube i
     where i.Student_id = si.Student_id
     order by convert(date,i.Entry_Date) desc
    ) x
where sd.student_Number = 700010068
  and se.Entry_Date > convert(date,'20011231')
  and se.School_Domain in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,13,24,25,26,27,28,29,30,31)
group by 
    sd.Student_Number
  , sd.First_Name
  , sd.Middle_Name
  , sd.Last_Name
  , sd.Name_Appendage
  , sd.dob
  , x.Last_Entry_Date
  , x.School_Name
order by 
    sd.Student_Number asc
  , x.Last_Entry_Date asc

注释/参考:

Bad habits to kick : using old-style JOINs - Aaron Bertrand Bad habits to kick : declaring varchar without (length) - Aaron Bertrand Bad habits : Putting NOLOCK everywhere - Aaron Bertrand Bad habits to kick : mis-handling date / range queries - Aaron Bertrand SQL Server 中日期/时间文字唯一真正安全的格式,至少对于 datetimesmalldatetime 是:YYYYMMDDYYYY-MM-DDThh:mm:ss[.nnn]

【讨论】:

我确实需要在指示为 max 的字段上设置 max...但我只需要最近的学校名称。我是否要使用我的原始代码并将交叉应用代码添加到它的末尾? 我拿了我的原始代码..在 FROM 语句之后添加了交叉应用。代码运行,没有错误,但我没有让学校名称出现在输出中。 我没有在输出中获得学校名称。如果我尝试在原始代码的末尾移动交叉应用,我会在单词“cross”附近得到错误的语法错误,在单词“order”附近得到错误的语法,所以我假设交叉应用必须在 FROM 语句之后....如果它在那里,它将运行,但输出中没有学校名称。任何想法为什么? @BillG 你是说School_Namenull 否,该列未出现在输出中。

以上是关于根据另一个字段的最大值获取字段的第一个值,同时还使用其他最大值字段的主要内容,如果未能解决你的问题,请参考以下文章

【SQL】根据一个字段分组求另一个字段的最大值,并带出其他字段

访问报告根据另一个字段值查找字段值

根据同一个表中另一个字段的值获取Mysql编号字段的净值

仅当数据集中另一个字段不同时才计算字段的表达式

如何根据另一个字段更新 mongodb 中的数组 dict 元素

根据模型的另一个字段的最大值返回模型的值