SQL:选择每个组的前1个,为每个组返回多个记录

时间:2018-09-06 00:39:48

标签: sql sql-server

我有一个看起来像这样的表:

| Id | InvestorFundId | Name | AccountKey | AsOfDate | AddedOn  |
| 1  | 11111          | Name1| Key1       | 9/5/2018 | 8/5/2018 |
| 2  | 11111          | Name2| Key1       | 9/3/2018 | 8/5/2018 |
| 3  | 22222          | Name3| Key2       | 9/2/2018 | 8/5/2018 |
| 4  | 33333          | Name4| Key3       | 9/2/2018 | 8/5/2018 |
| 5  | 33333          | Name5| Key3       | 9/4/2018 | 8/5/2018 |

我需要能够根据降序的InvestorFundIdAccountKey返回每个组的最新AsOfDate,名称和AddedOn

预期结果应如下所示:

| InvestorFundId | Name | AccountKey |
| 11111          | Name1| Key1       | 
| 22222          | Name3| Key2       |
| 33333          | Name5| Key3       | 

我看过一些帖子,但是我无法正确返回行,这是到目前为止的内容:

SELECT Name, AccountKey, H.InvestorFundId FROM
[Investor.Fund.History] H
CROSS APPLY(SELECT TOP 1 InvestorFundId 
FROM [Investor.Fund.History] 
WHERE  DataStatusId = 1 AND AsOfYearMonth <= 201806
ORDER BY AsOfDate DESC, AddedOn DESC) HS
ORDER BY H.InvestorFundId

但这将为我返回每个组的多个记录,而不是最近的记录。

我只想补充一点,当前的实现使用ROW_NUMBER,但是它太慢了,因此我正在研究其他解决方案。

谢谢

注意:我知道我的位置还有两个额外的列,我只是选择将它们从图中排除,但是您应该能够掌握要点

2 个答案:

答案 0 :(得分:2)

您可以使用CTE获取所需的数据。

USE tempdb;
GO

DECLARE @table TABLE (Id INT IDENTITY(1, 1), InvestorFundId INT, Name VARCHAR(50), AccountKey VARCHAR(50), AsOfDate DATE, AddedOn DATE);
INSERT INTO @table VALUES (11111, 'Name1', 'Key1', '9/5/2018', '8/5/2018');
INSERT INTO @table VALUES (11111, 'Name2', 'Key1', '9/3/2018', '8/5/2018');
INSERT INTO @table VALUES (22222, 'Name3', 'Key2', '9/2/2018', '8/5/2018');
INSERT INTO @table VALUES (33333, 'Name4', 'Key3', '9/2/2018', '8/5/2018');
INSERT INTO @table VALUES (33333, 'Name5', 'Key3', '9/4/2018', '8/5/2018');

;WITH CTE AS
(
    SELECT InvestorFundId, Name, AccountKey, ROW_NUMBER() OVER (PARTITION BY InvestorFundID ORDER BY AsOfDate DESC) AS RowId FROM @table
)
SELECT InvestorFundId, Name, AccountKey
    FROM CTE
    WHERE RowId = 1;

这是工作中的SQLFiddle

希望有帮助。

答案 1 :(得分:0)

您可以使用WITH TIES并只需在ROW_NUMBER中应用ORDER BY

Select top 1 with ties *
From History
Where DataStatusId = 1 and AsOfYearMonth = 201806
Order by 
Row_Number() over (partition by InvestorFundID order by AsOfDate desc)

或带有子查询

Select  *
    From (select * , RN= Row_Number() over (partition by InvestorFundID order by AsOfDate desc)
             From History
             Where DataStatusId = 1 and AsOfYearMonth = 201806) x
Where x.RN = 1

如果您发现执行速度较慢,那么我们需要查看执行计划来确定执行速度的原因。一个基于InvestorFundId的非聚集索引AsOfDate desc可以使此过程变得非常快。

Create nonclustered index indexName on
History (InvestorFundID, AsOfDate desc)