【问题标题】:SQL - Convert ROW_NUMBER function with multiple order bySQL - 用多个顺序转换 ROW_NUMBER 函数
【发布时间】:2018-09-10 21:50:49
【问题描述】:

我正在尝试将此查询转换为没有ROW_NUMBER 函数的子查询:

 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

基本上这是在一段时间内根据状态选择最近的[Investor.Fund.History]

到目前为止,我有这个:

SELECT InvestorFundId, MAX(AsOfDate) AS MaxAsOfDate, MAX(AddedOn) AS MaxAddedOn FROM [Investor.Fund.History]
WHERE DataStatusId = 1 AND AsOfDate <= (SELECT PeriodDate FROM [Fund.Period] WHERE Id = 5461)
GROUP BY InvestorFundId

我的查询给出了不正确的结果,它这样做是因为当我在多个列上使用 MAX 函数时,它不会像 ROW_NUMBER 那样根据两列的顺序选择最大值,而是选择 @987654326 @无论两列排序位置。

例如,如果我有一个如下所示的数据子集:

 | 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 AND AddedOn 正确返回表中的行

谁能帮忙?

【问题讨论】:

  • 呃...你有什么理由要改变这个吗?使用 ROW_NUMBER() 是这样的标准。
  • @ZLK 我刚开始在一家新公司工作,他们想删除 ROW_NUMBER 函数,他们说它没有优化
  • 呃...好像他们没有索引?我不确定it isn't optimized 在这里是什么意思。实际上,您编写的任何查询都必须遍历每个组并根据条件选择一行。在某些情况下,APPLY 或下面 gordon 的回答可能会更快,但它们也可能比 row_number() 排序慢。
  • @ZLK 他们确实在表格上有索引,但我确定他们缺少一些索引

标签: sql sql-server


【解决方案1】:

如果您有一个标识每一行的唯一 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
              );

? 用于唯一标识每一行的列。

这也可以使用APPLY

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;

【讨论】:

  • 我不认为第一个建议是价值 sql,但第二个是。尽管我刚刚检查过,与原始查询相比,您的建议使用了与批处理相关的 99% 的查询成本
猜你喜欢
  • 2020-01-08
  • 2018-09-12
  • 1970-01-01
  • 2018-06-20
  • 2013-09-23
  • 2017-08-05
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多