根据另一个字段的最大值获取字段的第一个值,同时还使用其他最大值字段
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 : declaringvarchar
without (length) - Aaron Bertrand
Bad habits : Putting NOLOCK everywhere - Aaron Bertrand
Bad habits to kick : mis-handling date / range queries - Aaron Bertrand
SQL Server 中日期/时间文字唯一真正安全的格式,至少对于 datetime
和 smalldatetime
是:YYYYMMDD
和 YYYY-MM-DDThh:mm:ss[.nnn]
【讨论】:
我确实需要在指示为 max 的字段上设置 max...但我只需要最近的学校名称。我是否要使用我的原始代码并将交叉应用代码添加到它的末尾? 我拿了我的原始代码..在 FROM 语句之后添加了交叉应用。代码运行,没有错误,但我没有让学校名称出现在输出中。 我没有在输出中获得学校名称。如果我尝试在原始代码的末尾移动交叉应用,我会在单词“cross”附近得到错误的语法错误,在单词“order”附近得到错误的语法,所以我假设交叉应用必须在 FROM 语句之后....如果它在那里,它将运行,但输出中没有学校名称。任何想法为什么? @BillG 你是说School_Name
是null
?
否,该列未出现在输出中。以上是关于根据另一个字段的最大值获取字段的第一个值,同时还使用其他最大值字段的主要内容,如果未能解决你的问题,请参考以下文章
【SQL】根据一个字段分组求另一个字段的最大值,并带出其他字段