有没有办法在一个查询中使用单独的递增值更新行组

时间:2014-04-16 11:33:37

标签: sql sql-server tsql

假设你有下表:

Id Index
1  3
1  1
2  1
3  3
1  5

我想要的是以下内容:

Id Index
1  0
1  1
2  0
3  0
1  2

您可能会注意到,目标是Id为相同的每一行,从零开始逐步更新Index列。

现在,我知道使用游标这是相当简单的,但出于好奇,有一种方法可以通过单个UPDATE查询来实现这一点,以某种方式与临时表,公共表表达式或类似的东西相结合?

5 个答案:

答案 0 :(得分:2)

是的,假设您并不真正关心新index值的值顺序。 SQL Server提供可更新的CTE和窗口函数,它们完全符合您的要求:

with toupdate as (
      select t.*, row_number() over (partition by id order by (select NULL)) as newindex
      from table t
     )
update toupdate
    set index = newindex;

如果您希望按特定顺序使用它们,则需要另一列来指定顺序。现有的index列无效。

答案 1 :(得分:2)

使用Row_number() -1和CTE,您可以写为:

CREATE TABLE #temp1(
Id int,
[Index] int)
INSERT INTO #temp1 VALUES (1,3),(1,1),(2,1),(3,3),(1,5);

--select * from #temp1;
With CTE as
(
    select t.*, row_number() over (partition by id order by (select null))-1 as newindex
    from #temp1 t
)
Update CTE 
set [Index] = newindex;

select * from #temp1;

Demo

答案 2 :(得分:0)

我不确定你为什么要这么做,但我很开心搞清楚! 这个解决方案依赖于你的表具有自我加入的主键...但你可以随时创建一个auto inc索引(如果不存在),这是一个一次性工作...这也有额外的好处,让你去考虑一下你想要的精确排序......因为目前没有办法说出哪个订单[ID]会得到[索引]。

UPDATE dbo.Example
SET [Index] = b.newIndex
FROM dbo.Example a
INNER JOIN (
    select 
        z.ID,
        z.[Index],
        (row_number() over (partition by ID order by (select NULL))) as newIndex
    from Example z
) b ON a.ID = b.ID AND a.[Index]=b.[Index] --Is this a unique self join for your table?.. no PK provided. You might need to make an index first.

答案 3 :(得分:0)

可能这就是你想要的

SELECT *,RANK() OVER(PARTITION BY Id ORDER BY [Index])-1 AS NewIndex FROM
(
    SELECT 1 AS Id,3 [Index]
    UNION
    SELECT 1,1
    UNION
    SELECT 2,1
    UNION
    SELECT 3,3
    UNION
    SELECT 1,5
) AS T

&安培;结果将作为
enter image description here

现在,如果您想更新表格,请执行此脚本

UPDATE tblname SET Index=RANK() OVER(PARTITION BY t.Id ORDER BY t.[Index])-1 
FROM tblname AS t

如果我遗失某些内容或需要任何进一步的帮助,请告诉我。

答案 4 :(得分:-1)

CREATE TABLE #temp1(
Id int,
Value int)

INSERT INTO #temp1 VALUES (1,2),(1,3),(2,3),(4,5)


SELECT
Id
,Value 
,ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Id) Id
FROM #temp1  

从这开始:)

给我的结果如

Id值计数
1 2 1
1 3 2
1 2 3
1 3 4
1 2 5
1 3 6
1 2 7
1 3 8
2 3 1
2 4 2
2 5 3
2 3 4
2 4 5
2 5 6
2 4 7
2 5 8
2 3 9
2 3 10
3 4 1
4 5 1
4 5 2
4 5 3
4 5 4