Sql 一个更好的替代ROW_NUMBER的方法是为每个组检索一条记录

Sql 一个更好的替代ROW_NUMBER的方法是为每个组检索一条记录,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,我们正在构建一个数据仓库,在这里我们希望捕获每种产品的价格,并每天保存这些数据。有一个包含FromDate和ToDate的表,这两个表都可以有NULL 找到今日价格的逻辑是: 忽略FromDate位于将来的任何记录。 忽略ToDate在过去的任何记录。 如果有多条记录满足上述要求,我们希望得到FromDate是最新的,ToDate是最接近当前日期的价格。 系统允许相同FromDate和ToDate的重复项,因此我们先按主键排序。 为了解决这个问题,我使用了一个带有分区的行号来对记录进行排序,并且

我们正在构建一个数据仓库,在这里我们希望捕获每种产品的价格,并每天保存这些数据。有一个包含FromDate和ToDate的表,这两个表都可以有NULL

找到今日价格的逻辑是:

忽略FromDate位于将来的任何记录。 忽略ToDate在过去的任何记录。 如果有多条记录满足上述要求,我们希望得到FromDate是最新的,ToDate是最接近当前日期的价格。 系统允许相同FromDate和ToDate的重复项,因此我们先按主键排序。 为了解决这个问题,我使用了一个带有分区的行号来对记录进行排序,并且只得到第一个。这是可行的,但是每天大约需要20分钟,而且对tempdb的影响相当大,因为我们有大约200万条记录将从这个查询中创建

是否有更好的替代方案可以提高查询的性能

请注意,fiddle是一个过度简化的数据示例,仅包含此问题的相关部分。

这是您的查询:

SELECT ProductId, @PriceDate AS PriceDate, Price
FROM (SELECT fp.*,
             ROW_NUMBER() OVER (PARTITION BY ProductId
                                ORDER BY COALESCE(FromDate, '19000101') DESC, COALESCE(ToDate, '21000101') ASC) AS RowNumber
      FROM FactPrices fp
      WHERE (FactPrices.FromDate IS NULL OR FactPrices.FromDate <= @PriceDate) AND
            (FactPrices.ToDate IS NULL OR FactPrices.ToDate >= @PriceDate)
     ) A
WHERE A.RowNumber = 1;
然后,在以下对象上创建索引:

(Prices, FromDateNotNull desc, ToDateNotNull asc)
(FromDateNotNull, ToDateNotNull)
然后,将查询编写为:

SELECT ProductId, @PriceDate AS PriceDate, Price
FROM (SELECT fp.*,
             ROW_NUMBER() OVER (PARTITION BY ProductId
                                ORDER BY FromDateNotNull DESC, ToDateNotNull
                              ) AS RowNumber
      FROM FactPrices fp
      WHERE FromDateNotNull <= @PriceDate AND
            ToDateNotNull >= @PriceDate
     ) A
WHERE A.RowNumber = 1;

表上有索引吗?是的,索引不是我的问题。我更想知道是否有一种不用解析函数就能做到这一点的方法。也许会对tempdb更友好一些。这可能是最好的方法,由于我拥有大量的数据,我可能不得不接受它。可能会有帮助。我会试试看!源数据通过SSI转储,这样我就可以在传入时删除空值。@Lock。在where子句中避免或将允许查询为查询使用索引。我重新调整了查询以删除所有or,现在是33秒。谢谢
SELECT ProductId, @PriceDate AS PriceDate, Price
FROM (SELECT fp.*,
             ROW_NUMBER() OVER (PARTITION BY ProductId
                                ORDER BY FromDateNotNull DESC, ToDateNotNull
                              ) AS RowNumber
      FROM FactPrices fp
      WHERE FromDateNotNull <= @PriceDate AND
            ToDateNotNull >= @PriceDate
     ) A
WHERE A.RowNumber = 1;