假设你有下表:
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查询来实现这一点,以某种方式与临时表,公共表表达式或类似的东西相结合?
答案 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;
答案 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
&安培;结果将作为
现在,如果您想更新表格,请执行此脚本
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