5

我研究并意识到我有一个独特的情况。

首先,由于我是新用户,因此我还不允许将图像发布到板上,因此请参阅下面的相应链接

我有多个表,其中列(不总是标识符列)按顺序编号,并且编号不应有任何中断。我的目标是确保这保持真实。

Down and Dirty 我们有一个“事件”表,我们在其中随机选择一定百分比的行并将这些行插入到表“结果”中。“结果”中的“ID”列被传递给一堆删除查询。

这或多或少确保了多个表中缺少行。

我的问题:找出一个 sql 查询,它将重新编号我指定的列。我宁愿不删除该列。

删除查询示例:

delete ItemVoid
from ItemTicket
join ItemVoid
on ItemTicket.item_ticket_id = itemvoid.item_ticket_id
where itemticket.ID in (select ID
            from results)

之前的示例表:

在此处输入图像描述

之后的示例表:

在此处输入图像描述

如您所见,根据 ID 列从两个表中删除了 2 行。所以现在我要弄清楚如何重新编号 item_ticket_id 和 item_void_id 列,其中较高的数字减少到缺失值,下一个最高的减少,等等。问题 #2,如果 item_ticket_id 更改以便在 ItemTickets 中连续,然后它必须更新 ItemVoid 的 item_ticket_id 中的更改。

我很感激您对此提供的任何建议。

4

3 回答 3

15

(回答一个老问题,因为这是我查找时的第一个搜索结果)
(MS T-SQL)

要对具有间隙的 ID 列(不是标识列)重新排序,可以仅使用带有 a 的简单 CTE 执行row_number()以生成新序列。通过UPDATECTE 的“虚拟表”工作,没有任何额外的问题,实际上更新了底层的原始表。
不用担心更新期间 ID 字段冲突,如果您想知道设置已经存在的 ID 时会发生什么,它不会遇到这个问题 - 原始序列一次更改为新序列。

WITH NewSequence AS
(
  SELECT
    ID, 
    ROW_NUMBER() OVER (ORDER BY ID) as ID_New
  FROM YourTable
)
UPDATE NewSequence  SET ID = ID_New;
于 2014-04-02T09:02:16.927 回答
3

由于您正在寻找这方面的建议,我的建议是您需要重新设计它,因为我发现您的设计存在很大缺陷。

而不是删除记录,然后经历重新编号剩余记录的麻烦,使用bit将记录标记为的标志Inactive。然后,当您查询记录时,只需包含一个WHERE子句以仅包含活动的记录:

SELECT *
FROM yourTable
WHERE Inactive = 0

这样您就不必担心重新编号记录。这也使您能够返回并查看将被删除的记录并且您不会丢失历史记录。

如果您真的想删除记录并重新编号,则可以通过以下方式执行此任务:

  1. 创建一个新表
  2. 使用新数字将原始数据插入新表
  3. 放下你的旧桌子
  4. 用更正的数字重命名新表

如您所见,对记录重新编号会涉及很多步骤。UPDATE当您可以执行一个位标志 时,您正在以这种方式创建更多的工作。

您可以将DELETE查询更改为类似于以下内容:

UPDATE ItemVoid
SET InActive = 1
FROM ItemVoid
JOIN ItemTicket
    on ItemVoid.item_ticket_id = ItemTicket.item_ticket_id
WHERE ItemTicket.ID IN (select ID from results)

标志要容易得多,这bit将是我推荐的方法。

于 2012-04-09T21:27:33.190 回答
2

您正在寻找的功能是一个窗口功能。在标准 SQL(SQL Server、MySQL)中,函数是 row_number()。您可以按如下方式使用它:

select row_number() over (partition by <col>)
from <table>

为了在您的情况下使用它,您将从表中删除行,然后使用 with 语句重新计算行号,然后使用更新分配它们。为了事务完整性,您可以将删除和更新包装到单个事务中。

Oracle 支持类似的功能,但语法略有不同。Oracle 将这些函数称为分析函数,它们支持对它们进行更丰富的操作。

我强烈警告您不要使用游标,因为它们的性能很差。当然,这不适用于标识列,因为无法修改这样的列。

于 2012-04-09T21:34:13.637 回答