1

我正在尝试构建一个 SQL 查询,该查询将采用一组行并对所有行上的一个字段重新编号,从它们都与会话 ID 匹配的位置开始。

例如更改前:

SessionID  |  LineNumber  |  LineContents
----------------------------------------------
74666      |  1           | example content
74666      |  2           | some other content
74666      |  3           | another line
74666      |  4           | final line

更改后(用户已删除第 2 行,因此“LineNumber”值已更新以反映新编号(即“第 3 行”现在已变为“第 2 行”等):

SessionID  |  LineNumber  |  LineContents
----------------------------------------------
74666      |  1           | example content
74666      |  2           | another line
74666      |  3           | final line

因此,以非正确的语法反映这一点将是沿着这些思路

i = 0;
UPDATE tbl_name
SET LineNumber = i++;
WHERE SessionID = 74666;

在没有运气的情况下搜索了很多,任何帮助都很棒:)

4

5 回答 5

2

使用Row_Number()函数和CTE

;WITH CTE AS (
  SELECT SessionID, LineNumber, LineContents,
         Row_Number() OVER(PARTITION BY SessionID ORDER BY LineNumber) Rn
  FROM Table1 
)
UPDATE CTE
SET LineNumber = Rn
WHERE SessionID = 74666;

小提琴演示

于 2013-10-28T15:52:15.943 回答
1

您可以在 UPDATE 语句中使用 ROW_NUMBER (MS SQL) 或 ROWNUM (Oracle) 或类似的。

检查这个

或这个

于 2013-10-28T15:39:09.253 回答
0

您有两种主要方法可以做到这一点。

第一个“低级”方式是这个(这里是 SQL Fiddle):

DELETE FROM TestTable 
WHERE SESSIONID = 74666 AND LineNumber = 3;

UPDATE TestTable SET LineNumber = LineNumber-1
WHERE SESSIONID = 74666 AND LineNumber > 3

select * from TestTable -- check the result

在这里,我们假设您知道 LineNumber 和 SessionID。

另一种方法是通过t-SQL Triggers,稍微复杂一点,但如果您不知道有关要删除的行的信息,它会对您有所帮助。试试看。

于 2013-10-28T15:47:53.077 回答
0
CREATE  TABLE Trial (
--   ID INT,
 SessionID INT , 
 LineNumber INT ,
 LineContent NVARCHAR(100)

)

INSERT  INTO dbo.trial
VALUES  ( 74666, 1, 'example content' ) ,
        ( 74666, 2, 'some other content' ),
        ( 74666, 4, 'another line' ),
        ( 74666, 5, 'final line' )

您可以最后删除 LineNumber 值,并可以在更新语句中使用该 id 来更新 LineNumbers 的其余部分,例如这里 Linenumber 3 被删除,所以,

   UPDATE dbo.trial SET LineNumber = LineNumber -1 WHERE LineNumber > 3
于 2013-10-28T15:57:06.497 回答
0

如果可能的话,我真的倾向于以不同的方式处理这个问题,并动态生成 Linenumber,以避免必须维护一个列,例如:

CREATE TABLE dbo.T 
(   
    LineNumberID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 
    SessionID INT NOT NULL,
    LineContents NVARCHAR(MAX) NOT NULL
);
GO
INSERT dbo.T (SessionID, LineContents)
VALUES 
    (74666, 'example content'),
    (74666, 'some other content'),
    (74666, 'another line'),
    (74666, 'final line');
GO
CREATE VIEW dbo.V
AS
    SELECT  LinenumberID,
            SessionID,
            Linenumber = ROW_NUMBER() OVER(PARTITION BY SessionID ORDER BY LinenumberID),
            LineContents
    FROM    dbo.T;
GO

在此您的视图为您提供所需的内容,如果我删除如下:

SELECT  *
FROM    dbo.V;

DELETE  dbo.V
WHERE   SessionID = 74666
AND     Linenumber = 3;

SELECT  *
FROM    dbo.V;

你得到输出:

LINENUMBERID    SESSIONID   LINENUMBER  LINECONTENTS
1               74666       1           example content
2               74666       2           some other content
3               74666       3           another line
4               74666       4           final line


LINENUMBERID    SESSIONID   LINENUMBER  LINECONTENTS
1               74666       1           example content
2               74666       2           some other content
4               74666       3           final line

SQL Fiddle 示例

因此,您无需实际更新字段即可维护您的连续行号字段。当然,这仅在您可以依赖字段(例如CreatedDate,或 ID 列)进行排序时才有效。否则,您将不得不使用触发器来维护它,并按照其他答案中的建议更新语句。

于 2013-10-28T16:09:05.030 回答