tsql - 设置顺序值而不循环/光标

时间:2011-08-02 01:18:43

标签: sql sql-server tsql group-by

我需要在数据表中设置一个非唯一标识符。这将是一个组内的顺序即。对于每个组,ID应从1开始,并以1的增量上升,直到该组的最后一行。

下表说明了这一点。 “新ID”是我需要填充的列。

Unique ID  Group ID  New ID
---------  --------  ------
1          1123      1
2          1123      2
3          1124      1
4          1125      1
5          1125      2
6          1125      3
7          1125      4

有没有办法在没有循环/光标的情况下这样做?如果循环/光标是唯一的方法,最有效的代码是什么?

由于

5 个答案:

答案 0 :(得分:6)

一种方法是在ROW_NUMBER() OVER(PARTITION BY ... ORDER BY ...)语句中使用UPDATE...FROM subqueryFROM clause

update MyTable set NewID = B.NewID
from
MyTable as A
inner join (select UniqueID, ROW_NUMBER() over (partition by GroupID order by UniqueID) as NewID from MyTable) as B on B.UniqueID = A.UniqueID
  • MSDN has a good sample to get you started:
  • 您需要在FROM子句中使用子查询才能使用Windows函数(Row_Index())
  • Partition By告诉服务器何时重置行号
  • Order By告诉服务器以哪种方式订购组的NewID

答案 1 :(得分:4)

我同意Damien在评论中的观点,但您不需要JOIN,您可以直接更新CTE。

;WITH cte AS
(
SELECT [New ID],
       ROW_NUMBER() OVER (PARTITION BY [Group ID] ORDER BY [Unique ID]) AS _NewID
FROM @T       
)
UPDATE cte
SET [New ID] = _NewID

Online Demo

答案 2 :(得分:0)

SELECT 
    UniqueId,
    GroupID,
    ROW_NUMBER() OVER (PARTITION BY GroupId ORDER BY UniqueId) AS NewIdx
FROM
    ....

答案 3 :(得分:0)

如果您运行旧版本的mssql

,此解决方案也可以使用
--Test table:

DECLARE @t table(Unique_ID int, Group_ID int,   New_ID int)

--Test data:

INSERT @t (unique_id, group_id)
SELECT 1, 1123 UNION ALL SELECT 2, 1123 UNION ALL SELECT 3, 1124 UNION ALL SELECT 4, 1125 UNION ALL SELECT 5, 1125 UNION ALL SELECT 6, 1125 UNION ALL SELECT 7, 1125 

--Syntax:

UPDATE t 
SET new_id = 
    (SELECT count(*) 
    FROM @t 
    WHERE t.unique_id >= unique_id and t.group_id = group_id 
    GROUP BY group_id) 
FROM @t t

--Result:

SELECT * FROM @t 

Unique_ID   Group_ID    New_ID
----------- ----------- -----------
1           1123        1
2           1123        2
3           1124        1
4           1125        1
5           1125        2
6           1125        3
7           1125        4

答案 4 :(得分:0)

如果您使用SS 2000

,则替代行号()
SELECT  UniqueID,
        GroupID,
        (SELECT COUNT(T2.GroupID)
        FROM    myTable T2
        WHERE   GroupID <= T1.GroupID) AS NewID
FROM    myTable T1