Sql server 如何根据条件订购?SQL Server

Sql server 如何根据条件订购?SQL Server,sql-server,sql-order-by,case,greatest-n-per-group,window-functions,Sql Server,Sql Order By,Case,Greatest N Per Group,Window Functions,例如,我有一个下表: ID NAME Company StartDate EndDate Status -------------------------------------------------------------------------------------- 50 Bob ABC 11-15-2016 02-

例如,我有一个下表:

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个工作,因此他们的活动工作将排在第一位,但如果他们有两个活动工作,如上面的示例,我只想提取具有最新开始日期的活动工作,或者如果两个活动工作具有相同的开始日期,则只需随机选择其中一个,并跳过另一个活动工作,然后继续他们最近的工作。活动作业的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
我已经尝试了下面的代码,但它无法检查两个活动作业状态并正确地给它们一个行号。根据上述条件,我只希望活动作业中的一个为rn=1,并且rn=2和rn=3将是前两个作业中的最后两个:

  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

您可以使用CTEs获取最新的活动工单和以前工单的注册护士,然后将两者合并:

;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
输出:


您可以使用CTEs获取最新的活动工单和以前工单的注册护士,然后将两者合并:

;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
输出:


您可以使用窗口函数来实现这一点。假设Active和Front是仅有的两个可能的状态值,则可以执行以下操作:

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)
最后,如果要使用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

您可以使用窗口函数来实现这一点。假设Active和Front是仅有的两个可能的状态值,则可以执行以下操作:

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)
最后,如果要使用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

他们可以有两个以上的工作吗?如果是这样的话,结果中大概还会出现一个?他们会有两个以上的活跃工作吗?如果是这样的话,大概结果中还会出现一个吗?是的,还有一个退休状态,我也希望包括在与前一个相同的标准中。此外,一些以前或退休的工作也可能有空的起始日期,但总是有空的起始日期EndDate@jwalls91:最后一个表达式似乎符合您的要求。当我尝试最后一个表达式时,以前的作业的起始日期为空时似乎存在问题。它给出了正确的活动参数,即rn=1,但同时也给出了一个具有NULL StartDate的前一个作业,即rn=1。因此,我想我需要找到一种方法来解释活动为rn=1的情况,也要解释前一个或已退休的情况,它总是有一个结束日期,但可能有一个空的起始日期,并按最近的日期对这些前一个或已退休的进行排序。如果它们没有活动的,那么只需按desc order按它们以前/退休的作业排序看起来就像在我编辑了部件大小写后,当status='Active'然后1 else 0到case when status='Active'然后0 else 1,这似乎现在可以正确地对它们进行排序,即使前者中的一个仍然是rn=1,对于前任/退休者,我需要它是rn=2和rn=3。这似乎是可行的,基本上创建了另一个具有正确编号的列。非常感谢。是的,还有一个退休状态,我也希望包括在与前一个相同的标准。此外,一些以前或退休的工作也可能有空的起始日期,但总是有空的起始日期EndDate@jwalls91:最后一个表达式似乎符合您的要求。当我尝试最后一个表达式时,以前的作业的起始日期为空时似乎存在问题。它给出了正确的活动参数,即rn=1,但同时也给出了一个具有NULL StartDate的前一个作业,即rn=1。因此,我想我需要找到一种方法来解释活动为rn=1的情况,也要解释前一个或已退休的情况,它总是有一个结束日期,但可能有一个空的起始日期,并按最近的日期对这些前一个或已退休的进行排序。如果它们没有活动的,那么只需按desc order按它们以前/退休的作业排序看起来就像在我编辑了部件大小写后,当status='Active'然后1 else 0到case when status='Active'然后0 else 1,这似乎现在可以正确地对它们进行排序,即使前者中的一个仍然是rn=1,对于前任/退休者,我需要它是rn=2和rn=3。这似乎是可行的,基本上创建了另一个具有正确编号的列。非常感谢。