SQL-按多个顺序转换行数函数
我正在尝试将此查询转换为不带SQL-按多个顺序转换行数函数,sql,sql-server,Sql,Sql Server,我正在尝试将此查询转换为不带行号函数的子查询: SELECT InvestorFundId, AsOfDate, AddedOn FROM ( SELECT ROW_NUMBER() OVER (PARTITION BY InvestorFundId ORDER BY AsOfDate DESC, AddedOn DESC) AS HistoryIndex, * FROM [Investor.Fund.History]
行号
函数的子查询:
SELECT InvestorFundId, AsOfDate, AddedOn FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY InvestorFundId ORDER BY AsOfDate DESC, AddedOn DESC) AS HistoryIndex, *
FROM [Investor.Fund.History]
WHERE DataStatusId = 1 AND AsOfDate <= (SELECT PeriodDate FROM [Fund.Period] WHERE Id = 5461)
) G WHERE HISTORYINDEX = 1
我的查询给出了不正确的结果,这是因为当我对多列使用MAX
函数时,它不会像行号那样根据两列的顺序选择MAX,而是选择MAX
,无论两列的顺序位置如何
例如,如果我有如下数据子集:
| InvestorFundId | AsOfDate | AddedOn |
| 1 | 2010-10-01 00:00:00.000 | 2012-04-18 09:29:33.277 |
| 1 | 2006-11-01 00:00:00.000 | 2013-04-18 11:25:23.033 |
ROW_NUMBER函数将返回以下内容:
| 1 | 2010-10-01 00:00:00.000 | 2012-04-18 09:29:33.277 |
而我的函数返回:
| 1 | 2010-10-01 00:00:00.000 | 2013-04-18 11:25:23.033 |
如您所见,它实际上不是表中的一行
我希望函数根据MAX
AsOfDATE
和AddedOn
正确返回表中的行
有人能帮忙吗?如果您有一个唯一的id来标识每一行,那么您可以执行以下操作:
WITH ifh as (
SELECT InvestorFundId, AsOfDate, AddedOn
FROM [Investor.Fund.History]
WHERE DataStatusId = 1 AND AsOfDate <= (SELECT PeriodDate FROM [Fund.Period] WHERE Id = 5461)
)
SELECT ifh.*
FROM ifh
WHERE ifh.? = (SELECT ?
FROM ifh ifh2
WHERE ifh2.InvestorFundId = ifh.InvestorFundId
ORDER BY AsOfDate DESC, AddedOn DESC
FETCH FIRST 1 ROW ONLY
);
UH你想改变这一切有什么原因吗?使用ROW_NUMBER()是这样做的标准。@ZLK我刚开始在一家新公司工作,他们想删除ROW_NUMBER函数,但他们说这不是优化的结果。。。好像他们没有索引?我不确定这里没有优化的
意味着什么。实际上,您编写的任何查询都必须遍历每个组,并根据条件选择一行。有些情况下,APPLY
或下面gordon的答案可能会更快,但也可能比row_number()排序慢。@ZLK它们确实在表上有索引,我确信它们缺少一些,尽管我认为第一个建议不是值sql,但第二个是值sql。尽管我刚刚检查过,您的建议使用了与原始查询相比批次的99%的查询成本
WITH ifh as (
SELECT InvestorFundId, AsOfDate, AddedOn
FROM [Investor.Fund.History]
WHERE DataStatusId = 1 AND AsOfDate <= (SELECT PeriodDate FROM [Fund.Period] WHERE Id = 5461)
)
SELECT ifh.*
FROM ifh
WHERE ifh.? = (SELECT ?
FROM ifh ifh2
WHERE ifh2.InvestorFundId = ifh.InvestorFundId
ORDER BY AsOfDate DESC, AddedOn DESC
FETCH FIRST 1 ROW ONLY
);
select ifh2.*
from (select distinct InvestorFundId
from ifh
) i cross apply
(select top (1) ifh2.*
from ifh ifh2
where fh2.InvestorFundId = i.InvestorFundId
order by AsOfDate DESC, AddedOn DESC
fetch first 1 row only
) ifh2;