ROW_NUMBER() 仅适用于前 N 条记录

ROW_NUMBER() to be applied only for top N records

我有一个方案可以根据 Id 列获取结果集的零索引值。我可以通过 ROW_NUMBER() 来实现。但是现在预期的行为发生了轻微的变化。

预期是,对于 前五条记录 只需要显示 IndexValue,对于其余条目 IndexValue 应该是 NULL.

为了实现这一点,我通过 ROW_NUMBER() 设置了 IndexValue,推入 table 变量 @PopulateValues,然后使用 UPDATE 我得到了预期结果如下图:

我试过的:

-- Actual Table in database
DECLARE @OriginalTable TABLE (Id INT IDENTITY(1, 1), [Name] VARCHAR (255));
INSERT INTO @OriginalTable ([Name]) VALUES 
('Name 01'), ('Name 02'), ('Name 03'), ('Name 04'), ('Name 05'), 
('Name 06'), ('Name 07'), ('Name 08'), ('Name 09'), ('Name 10'), 
('Name 11'), ('Name 12'), ('Name 13'), ('Name 14'), ('Name 15');

-- Table variable for the populate calculation
DECLARE @PopulateValues TABLE (Id INT, [Name] VARCHAR (255), IndexValue INT NULL);
INSERT INTO @PopulateValues (Id, [Name], IndexValue)
SELECT Id, [Name], ROW_NUMBER() OVER (ORDER BY Id) - 1 AS IndexValue
FROM @OriginalTable;

UPDATE @PopulateValues SET IndexValue = NULL WHERE IndexValue >= 5;

SELECT * FROM @PopulateValues;

通过这种方法,我能够实现我的期望,但是有没有其他方法可以将 ROW_NUMBER() 仅应用于 TOP N 记录,而 SELECT?

您可以在查询中使用 case 表达式:

SELECT Id, Name, CASE WHEN IndexValue < 5 THEN IndexValue END AS IndexValue
FROM   (SELECT Id, Name, ROW_NUMBER() OVER (ORDER BY Id) - 1 AS IndexValue
        FROM   @OriginalTable) t

您可以像这样将 CASE 语句与子查询一起使用:

INSERT INTO @PopulateValues (Id, [Name], IndexValue)
SELECT x.[Id], x.[Name], CASE WHEN x.IndexValue < 5 THEN x.IndexValue ELSE NULL END AS [IndexValue]
FROM
(
SELECT Id, [Name], ROW_NUMBER() OVER (ORDER BY Id) - 1 AS IndexValue
FROM @OriginalTable;
) AS x

因为我发现了另一种使用 Logical Function - IIF 的可能方式(从 SQL Server 2012 开始),所以查询将是:

SELECT Id, [Name], IIF(IndexValue < 5, IndexValue, NULL) AS IndexValue 
FROM  ( SELECT Id, Name, ROW_NUMBER() OVER (ORDER BY Id) - 1 AS IndexValue
        FROM @OriginalTable ) Q