SQL Server:在给定数据之后获取第一行

时间:2019-02-01 09:58:52

标签: sql sql-server

我正在准备使用SQL Server从数据库中获取数据的查询。请在下面查询。有一个表AssociateStatus。该表包含员工的当前状态。 AssociateStatus_HST表包含所有状态更改。我想在[Status Changed Date]列中更改状态。

通过查询,我将获得状态3之后的所有更新日期。但是,我只希望单独获取下一个更新日期。请注意,状态更改可以按任何顺序进行。

SELECT 
    AssociateId,[Status], UpdatedAt, 
    ASH.UpdatedAt AS [Status Changed Date] 
FROM
    AssociateStatus_HST AST 
LEFT OUTER JOIN  
    (SELECT
         ProposalBidId,UpdatedAt
     FROM
         AssociateStatus_HST) ASH ON (ASH.StatusID = AST.StatusID AND ASH.UpdatedAt > AST.UpdatedAt)
WHERE 
    [Status] = 3

此查询的示例输出:

  AssociateId   Status  UpdatedAt  Status Changed Date
 --------------------------------------------------------
  1234            3       21-1-19       24-1-19
  1234            3       21-1-19       27-1-19
  4567            3       20-1-19       25-1-19

预期产量

  AssociateId   Status  UpdatedAt  Status Changed Date
 --------------------------------------------------------
  1234          3       21-1-19    24-1-19
  4567          3       20-1-19    25-1-19

4 个答案:

答案 0 :(得分:2)

尝试在没有子查询的情况下使用GROUP BY

SELECT 
   AssociateId, 
   [Status], 
   Max( UpdatedAt) UpdatedAt, 
   Min(ASH.UpdatedAt) AS [Status Changed Date] 
FROM AssociateStatus_HST AST 
LEFT OUTER JOIN AssociateStatus_HST ASH
    ON 
        ASH.StatusID = AST.StatusID and ASH.UpdatedAt > AST.UpdatedAt   
WHERE [Status] = 3
GROUP BY AssociateId, Status

和一个示例(我已将日期修改为ANSI格式):

DECLARE @FooTable TABLE
(
    AssociateId INT,
    Status INT,
    UpdatedAt VARCHAR(50),
    StatusChangedDate VARCHAR(50)
)

INSERT INTO @FooTable
(
    AssociateId,
    Status,
    UpdatedAt,
    StatusChangedDate
)
VALUES
  (1234,          3,       '2019-21-1', '2019-1-24')
, ( 1234,          3,       '2019-19-1',    '2019-1-19')
, (4567,          3,       '2019-1-19',    '2019-1-25')

SELECT 
  ft.AssociateId
, ft.Status 
, MAX(ft.UpdatedAt) UpdatedAt
, MIN(ft.StatusChangedDate) StatusChangedDate
FROM @FooTable ft
GROUP BY ft.AssociateId, ft.Status

输出:

AssociateId Status  UpdatedAt   StatusChangedDate
1234    3   2019-21-1   2019-1-19
4567    3   2019-1-19   2019-1-25

答案 1 :(得分:2)

您可以使用APPLY

SELECT AST.*, ASH.*
FROM AssociateStatus_HST AST OUTER APPLY
     (SELECT TOP (1) ASH.UpdatedAt AS [Status Changed Date] 
      FROM AssociateStatus_HST AS ASH
      WHERE ASH.AssociateId = AST.AssociateId AND AST.StatusID = ASH.StatusID AND ASH.UpdatedAt > AST.UpdatedAt AND ASH.[Status] = 3
      ORDER BY ASH.UpdatedAt 
     ) ASH'

答案 2 :(得分:1)

您可以尝试使用row_number()函数

select * from 
(
SELECT AssociateId,[Status],UpdatedAt, ASH.UpdatedAt AS [Status Changed Date],
row_number() over(partition by AssociateId order by ASH.UpdatedAt) as rn
FROM AssociateStatus_HST AST 
LEFT OUTER JOIN 
(
  SELECT ProposalBidId,UpdatedAt FROM AssociateStatus_HST 
) ASH ON 
ASH.StatusID = AST.StatusID and ASH.UpdatedAt > AST.UpdatedAt
WHERE [Status] = 3
) A where rn=1

答案 3 :(得分:1)

使用row_number()窗口函数

with cte as (

SELECT 
   AssociateId,[Status],UpdatedAt, ASH.UpdatedAt AS [Status Changed Date] 
  ,row_number() over(partition by AssociateId,[Status] order by ASH.UpdatedAt) rn
FROM AssociateStatus_HST AST 
LEFT OUTER JOIN (
SELECT
    ProposalBidId,UpdatedAt
FROM
    AssociateStatus_HST 
    ) ASH
ON (
    ASH.StatusID = AST.StatusID and ASH.UpdatedAt > AST.UpdatedAt
)
WHERE [Status] = 3
) select * from cte where rn=1