如何使ROW_NUMBER与重复记录一起使用?

时间:2015-06-23 21:05:33

标签: sql-server sql-server-2008 tsql

我有一个表,其中包含重复的事务记录。这些都不是重复,但需要为它们分配值,使它们对表是唯一的。使用记录是按顺序查看它们,我使用ROW_NUMBER按ID和ORDER BY Time对它们进行分区。

有时它有效。有时会失败。

示例

CASE WHEN [Record] = 'Start' 
     THEN 0 
ELSE -1 + ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [Date] DESC
END AS [RowNo]

预期结果

ID,   Date,  RowNo
2002, 12:30, 1
2002, 12:29, 2
2002, 12:29, 3
2002, 12:29, 4
2002, 12:28, 5
3212, 01:10, 1
3212, 01:09, 2
3212, 01:08, 3

实际结果

ID,   Date,  RowNo
2002, 12:30, 1
2002, 12:29, 2 <---Right
2002, 12:29, 2 <---Wrong
2002, 12:29, 3 <---Right
2002, 12:28, 4
3212, 01:10, 1
3212, 01:09, 2
3212, 01:08, 3

是否有更好的方法来确保准确性?

2 个答案:

答案 0 :(得分:4)

嗯。 ROW_NUMBER()可以处理重复记录。 (当存在重复时,哪个行将获得哪个值不确定。)

您的陈述中还有其他内容,但未显示。连接操作,GROUP BY,一些额外的过滤。我们不知道那是什么,但我们知道ROW_NUMBER()确实适用于重复项。

修改

这很可疑:

CASE WHEN [Record] = 'Start' 
    THEN 0 
ELSE -1 + ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [Date] DESC
END AS [RowNo]

我以前从未在CASE表达式中看到过分析函数。在我看来, ROW_NUMBER() 只会在ELSE的上下文中进行评估。 (我不确定SQL Server实际上如何处理它。)

如果我希望RowNo为0,1,2,......我只会减去1 ......

ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [Date] DESC) - 1 AS RowNo

如果需要在[Record] = 'Start'评估ROW_NUMBER时将条件纳入PARTITION,那么我会将其纳入 OVER(PARTITION BY [ID],CASE WHEN [Record]='Start' THEN 0 END ORDER BY ...)

ROW_NUMBER()

如果我需要操作ROW_NUMBER()返回的值,我会找到一种方法来在内联视图或CTE的上下文中进行评估,以获得评估和返回的值,并且然后使用外部查询中返回的值进行清理。

重点是$variable="mike;john;mike"; $each=explode(';',$variable); //print_r($each); $new=array_unique($each); echo implode(';',$new); //mike;john 可以正常复制。如果你得到的结果是你没想到的,那是因为语句中还有其他东西,例如CASE表达式,或者连接,或者什么。

答案 1 :(得分:1)

获取每行唯一标识符的另一种方法是使用%% Physloc %%(或SQL Server 2005中的%% lockres %%)虚拟列,它允许标识行的物理地址:

SELECT Id, Date, %%Physloc%%
FROM [your_table]

通过这种方式,您可以获得比ROW_NUMBER更好的表格。