如何根据条件进行ORDER BY? SQL 服务器
How to ORDER BY based on condition? SQL Server
我下面有一个 table 例如:
ID NAME Company StartDate EndDate Status
--------------------------------------------------------------------------------------
50 Bob ABC 11-15-2016 02-05-2017 Former
50 Bob XYZ 05-06-2014 05-06-2015 Former
50 Bob EFG 06-10-2019 NULL Active
50 Bob LMN 07-05-2019 NULL Active
我试图按降序列出他们最近的 3 个工作,因此他们的“活跃”工作将排在第一位,但如果他们有 2 个“活跃”工作,如上例,我只想拉“具有最近开始日期的“活动”工作,或者如果两个“活动”工作具有相同的开始日期,则只需随机选择其中一个,并跳过另一个活动,然后继续他们最近的前工作。 “活动”作业将始终具有 NULL EndDate 值。
所以我要查找的结果集如下所示:
ID NAME Company StartDate EndDate Status rn
----------------------------------------------------------------------------------------------
50 Bob LMN 07-05-2019 NULL Active 1
50 Bob ABC 11-15-2016 02-05-2017 Former 2
50 Bob XYZ 05-06-2014 05-06-2015 Former 3
我试过下面的代码,但它无法检查两个活动作业状态并正确地给它们一个行号。根据上述条件,我只希望其中一个 Active 作业为 rn = 1,并且 rn = 2 和 rn = 3 将是最后 2 个“前”作业:
select *, row_number() over (partition by ID, NAME order by CASE WHEN Status = 'Active' AND
EndDate is NULL THEN Status END desc, EndDate desc
) rn
from employment
您可以使用 CTE 获取最新的 Active 作业和 Former 作业的 rn,然后 UNION 两者:
;with cte1 as
(
select Id, Name, C.Company, C.StartDate, C.EndDate, C.Status, rn = 1
From employment E
Outer Apply
(
Select top 1 E2.Company,
E2.StartDate,
E2.EndDate,
E2.Status
From employment E2
where E.Id = E2.Id and E.Name = E2.Name
and E2.Status = 'Active'
order by E2.StartDate desc
) C
group by E.Id, E.Name, C.Company, C.StartDate, C.EndDate, C.Status
),
cte2 as
(
select *, 1 + row_number() over (partition by ID, NAME order by StartDate desc
) rn
from employment
where Status = 'Former'
)
select * from cte1
union
select * from cte2
where rn <= 3
order by Id asc, Name asc, StartDate desc
输出:
您可以使用 window 函数来做到这一点。假设“活跃”和“前任”是仅有的两个可能的状态值,您可以这样做:
select *
from (
select t.*,
row_number() over (partition by id, status order by startDate desc) rn
from mytable t
) t
where
(status = 'Active' and rn = 1)
or (status <> 'Active' and rn <= 2)
如果可能还有其他状态,那么您可以将window函数更改为:
row_number() over (
partition by id, case when status = 'Active' then 1 else 0 end
order by startDate desc
) rn
最后,如果您想使用 startDate
订购“有效”记录并 endDate
订购其他记录:
row_number() over (
partition by id, case when status = 'Active' then 1 else 0 end
order by case when status = 'Active' then startDate else endDate end desc
) rn
我下面有一个 table 例如:
ID NAME Company StartDate EndDate Status
--------------------------------------------------------------------------------------
50 Bob ABC 11-15-2016 02-05-2017 Former
50 Bob XYZ 05-06-2014 05-06-2015 Former
50 Bob EFG 06-10-2019 NULL Active
50 Bob LMN 07-05-2019 NULL Active
我试图按降序列出他们最近的 3 个工作,因此他们的“活跃”工作将排在第一位,但如果他们有 2 个“活跃”工作,如上例,我只想拉“具有最近开始日期的“活动”工作,或者如果两个“活动”工作具有相同的开始日期,则只需随机选择其中一个,并跳过另一个活动,然后继续他们最近的前工作。 “活动”作业将始终具有 NULL EndDate 值。
所以我要查找的结果集如下所示:
ID NAME Company StartDate EndDate Status rn
----------------------------------------------------------------------------------------------
50 Bob LMN 07-05-2019 NULL Active 1
50 Bob ABC 11-15-2016 02-05-2017 Former 2
50 Bob XYZ 05-06-2014 05-06-2015 Former 3
我试过下面的代码,但它无法检查两个活动作业状态并正确地给它们一个行号。根据上述条件,我只希望其中一个 Active 作业为 rn = 1,并且 rn = 2 和 rn = 3 将是最后 2 个“前”作业:
select *, row_number() over (partition by ID, NAME order by CASE WHEN Status = 'Active' AND
EndDate is NULL THEN Status END desc, EndDate desc
) rn
from employment
您可以使用 CTE 获取最新的 Active 作业和 Former 作业的 rn,然后 UNION 两者:
;with cte1 as
(
select Id, Name, C.Company, C.StartDate, C.EndDate, C.Status, rn = 1
From employment E
Outer Apply
(
Select top 1 E2.Company,
E2.StartDate,
E2.EndDate,
E2.Status
From employment E2
where E.Id = E2.Id and E.Name = E2.Name
and E2.Status = 'Active'
order by E2.StartDate desc
) C
group by E.Id, E.Name, C.Company, C.StartDate, C.EndDate, C.Status
),
cte2 as
(
select *, 1 + row_number() over (partition by ID, NAME order by StartDate desc
) rn
from employment
where Status = 'Former'
)
select * from cte1
union
select * from cte2
where rn <= 3
order by Id asc, Name asc, StartDate desc
输出:
您可以使用 window 函数来做到这一点。假设“活跃”和“前任”是仅有的两个可能的状态值,您可以这样做:
select *
from (
select t.*,
row_number() over (partition by id, status order by startDate desc) rn
from mytable t
) t
where
(status = 'Active' and rn = 1)
or (status <> 'Active' and rn <= 2)
如果可能还有其他状态,那么您可以将window函数更改为:
row_number() over (
partition by id, case when status = 'Active' then 1 else 0 end
order by startDate desc
) rn
最后,如果您想使用 startDate
订购“有效”记录并 endDate
订购其他记录:
row_number() over (
partition by id, case when status = 'Active' then 1 else 0 end
order by case when status = 'Active' then startDate else endDate end desc
) rn