SQL 将索引(订单值)设置为列

Posted

技术标签:

【中文标题】SQL 将索引(订单值)设置为列【英文标题】:SQL Set Index (order value) to column 【发布时间】:2018-02-05 10:45:08 【问题描述】:

短篇小说

我的Requests 有“行”表。目前,当我向请求添加新行时,无法对其进行排序,因此我添加了Index 列。这将能够添加新行并按照我的意愿对它们进行排序。

我想做的事

我想编写 MSSQL 脚本,由InvoiceRequestId 将旧行的默认值设置Index (0, 1, 2)。目前应该按原样设置(Id 顺序)。

当前表

Id    InvoiceRequestId  Index
2734  620               0
2735  620               0
2736  621               0
2737  622               0
2738  622               0
2739  622               0
...

我想要达到的目标

Id    InvoiceRequestId  Index
2734  620               0
2735  620               1
2736  621               0
2737  622               0
2738  622               1
2739  622               2
...

编辑

我明白了,有些人开始只为这些行发布答案。这应该是一般的解决方案,我的错,我之前没有澄清这一点。

解决方案

所以感谢下面的答案和这个主题 SQL Update with row_number() ,我找到了以下解决方案:

With IndexUpdate As
(
    SELECT [Index],
    ROW_NUMBER() OVER (PARTITION BY InvoiceRequestID ORDER BY ID) -1 as RN
    FROM [InvoiceRequestRows]
)
UPDATE IndexUpdate SET [Index]=RN

【问题讨论】:

我已经更新了更新的答案,你也可以检查一下。 【参考方案1】:

你可以使用row_number()函数

select *,
      (row_number() over(partition by InvoiceRequestId order by Id)-1)  
from table

编辑:为子查询结果集使用CTE,以便用新创建的索引更新索引

;with cte as
(
  select *,
       (row_number() over(partition by InvoiceRequestId order by Id)-1) newindex 
  from table
)
update t set t.[Index] = c.newindex 
from cte c
join table t on t.Id = c.Id 

【讨论】:

谢谢你的回答,但是我如何在更新方法中使用它,所以我的 [Index] 列会使用这些值? 为什么要使用join?声明,我把我原来的问题作为解决方案似乎也有效。 @Taurib .. 是的,不需要明确的join 但是,join 将保证使用适当的id's 更新您的索引【参考方案2】:

如果您想获得这些结果,您不需要添加列,您可以使用 ROW_NUMBER 函数,例如

DECLARE @table TABLE(Id INT, InvoiceRequestId INT);
INSERT INTO @table
VALUES
(2734, 620),
(2735, 620),
(2736, 621),
(2737, 622),
(2738, 622),
(2739, 622);

SELECT Id,
       InvoiceRequestId,
       ROW_NUMBER() OVER(PARTITION BY InvoiceRequestId ORDER BY Id) AS [Index]
FROM @table;

会给你:

Id  InvoiceRequestId    Index
2734    620             1
2735    620             2
2736    621             1
2737    622             1
2738    622             2
2739    622             3

它从 1 而不是 0 开始计数,但结果是相同的。如果需要为 0,可以添加“-1”

如果您仍想添加该列,那么您可以使用相同的函数构建一个临时表并从那里插入

【讨论】:

【参考方案3】:

以下查询应该可以工作。 ROW_NUMBER -1 正在完成,因为您正在寻找要从 0 开始盯着的索引。

    WITH Requests as (
    select * from (values 
        (2734 , 620 ,   0)
        ,(2735,  620 ,   0)
        ,(2736,  621 ,   0)
        ,(2737 , 622 ,   0)
        ,(2738,  622 ,   0)
        ,(2739,  622 ,   0)
      ) t (Id, InvoiceRequestId  , [Index])
    )

SELECT Id, InvoiceRequestId,(ROW_NUMBER() 
    OVER(PARTITION BY  InvoiceRequestId 
    ORDER BY Id, InvoiceRequestId ASC)-1) AS Index
 FROM Requests

你会得到如下输出。

Id    InvoiceRequestId  Index
2734  620               0
2735  620               1
2736  621               0
2737  622               0
2738  622               1
2739  622               2

要更新回来,您可以使用以下查询

UPDATE R
SET R.[Index] = N.[Index]

FROM Requests R
INNER JOIN
(

SELECT Id, InvoiceRequestId,(ROW_NUMBER() 
    OVER(PARTITION BY  InvoiceRequestId 
    ORDER BY Id, InvoiceRequestId ASC)-1) AS [Index]
 FROM Requests
 ) N
 ON N.Id = R.ID AND N.InvoiceRequestId= R.InvoiceRequestId

【讨论】:

【参考方案4】:

您可以使用 SQL Server 中的 RANK 函数之一,例如创建一个名为 NewIndex 的新列

链接here

SELECT ID, InvoiceRequestID, 
ROW_NUMBER() OVER (PARTITION BY InvoiceRequestID ORDER BY ID) -1 AS NewIndex
FROM SomeTable

要更新Index 列,您可以使用它(虽然我还没有测试过这段代码...)

UPDATE SomeTable
SET [Index] = ROW_NUMBER() OVER (PARTITION BY InvoiceRequestID ORDER BY ID) -1

【讨论】:

感谢您的回复。您的解决方案只是选择,但我如何更新 [Index] 以设置此值? @Taurib 您可以在 UPDATE 语句中使用相同的表达式,我将编辑我的答案 用你的更新脚本我得到Windowed functions can only appear in the SELECT or ORDER BY clauses.

以上是关于SQL 将索引(订单值)设置为列的主要内容,如果未能解决你的问题,请参考以下文章

使用 SQL 将数据从行转换为列

pandas读取csv数据使用reset_index函数把行索引重置为列数据(level参数设置将原行索引中的指定层转化为列数据设置drop参数则删除转化后的数据列)

pandas读取csv数据使用reset_index函数把行索引重置为列数据(level参数设置将原行索引中的指定层转化为列数据设置drop参数则删除转化后的数据列)

保留现有列并将行转换为列[重复]

SQL 索引与执行计划

pandas读取csv数据header参数指定作为列索引的行索引列表形成复合(多层)列索引使用reset_index函数把行索引重置为列数据(level参数设置将原行索引中的指定层转化为列数据)